Count bounded slices

By | December 31, 2014
Share the joy
  •  
  •  
  •  
  •  
  •  
  •  

Problem:
Return the pair of indices that forms the slice where the difference between the maximum and minimum in the slice <= k. Pair of indices shouldn’t be like (i,i).
Consider k is 2. And the array is 3 5 7 6 3.
Output: (0,1) (1,2) (1,3) (2,3)

Analysis:
A brute-force idea is to recursively find max/min of all indices. Once finding the max/min, output the result. And use hashmap store the history results to reduce duplicate calculation. Because it iterates all possible indices, the time/space complexity is optimized.
This idea is to maintain a ascend queue. Queue front stores the min value. Queue end stores the max valule. Each time, add new element into the sorted queue. Check the max-min. If it is smaller than k, print the results with new element. If max-min is greater than k, we need to adjust the queue before print the results.
It is similar to max value in a sliding widow. But the difference is that in this case, the queue maintain both min value in the front, max value in the end. And max in sliding window only store a max value(or min value).
I provide the following process for understanding:


There are N elements. For each element, it takes O(logn) to insert into the queue, and O(n) to output the result. So the total time complexity is O(n*(n+logn)), which is O(n^2). Not considering result output, it is O(nlogn).
Complete code is following:

  1. import java.util.ArrayList;
  2. import java.util.Collections;
  3. import java.util.Comparator;
  4. public class CountBoundedSlices {
  5.     public static void main(String[] args) {
  6.         int[] arr = {1, 3, 2, 4, 5, 1, 6, 7, 9};
  7.         countBoundedSlices(arr, 2);
  8.     }
  9.     public static void countBoundedSlices(int[] arr, int k){
  10.         BoundedSlicesSData curr = new BoundedSlicesSData(arr[0],0);
  11.         ArrayList queue = new ArrayList();
  12.         queue.add(curr);
  13.         for(int i=1;i < arr.length;i++){
  14.             curr = new BoundedSlicesSData(arr[i], i);
  15.             queue.add(curr);
  16.             Collections.sort(queue, new BoundedSlicesSDataComparator());    //add current element into queue.
  17.             BoundedSlicesSData front = queue.get(0);
  18.             BoundedSlicesSData end = queue.get(queue.size()-1);
  19.             if(end.value-front.value>k&&curr.value==end.value){
  20.                 //Got a larger value at queue end. It makes max-min>k. So modify the queue front.
  21.                 while(end.value-front.value>k){
  22.                     int front_time = front.position;
  23.                     queue.remove(0);
  24.                     front = queue.get(0);
  25.                     while(front.position < front_time){    //delete those elements, which are earlier inserted than front
  26.                         queue.remove(0);
  27.                         front = queue.get(0);
  28.                     }//while
  29.                 }//while
  30.                 for(int j=0;j < queue.size()-1;j++){
  31.                     printResult(queue.get(j).position, end.position);
  32.                 }
  33.             }
  34.             else if(end.value-front.value>k&&curr.value==front.value){
  35.                 //Got a smaller value at queue front. It makes max-min>k. So modify the queue end.
  36.                 while(end.value-front.value>k){
  37.                     int end_time = end.position;
  38.                     queue.remove(queue.size()-1);
  39.                     end = queue.get(queue.size()-1);
  40.                     while(end.position < end_time){    //delete those elements, which are earlier inserted than front
  41.                         queue.remove(queue.size()-1);
  42.                         end = queue.get(queue.size()-1);
  43.                     }//while
  44.                 }//while
  45.                 for(int j=queue.size()-1;j>0;j–){
  46.                     printResult(queue.get(j).position, front.position);
  47.                 }
  48.             }//if
  49.             else{
  50.                 //insertation of curr doesn’t affect max, min. Print result with curr
  51.                 for(int j=0;j < queue.size();j++){
  52.                     BoundedSlicesSData printAux = queue.get(j);
  53.                     if(printAux.position==curr.position){
  54.                         continue;
  55.                     }
  56.                     printResult(printAux.position, curr.position);
  57.                 }
  58.             }//if
  59.         }//for
  60.     }
  61.     public static void printResult(int i, int j){
  62.         if(i < j){
  63.             System.out.println(“(“+i+”,”+j+”)”);
  64.         }
  65.         else{
  66.             System.out.println(“(“+j+”,”+i+”)”);
  67.         }
  68.     }
  69. }
  70. /*
  71.  * The queue should store both value and position. So create this class for convinent.
  72.  */
  73. class BoundedSlicesSData{
  74.     int value;
  75.     int position;
  76.     public BoundedSlicesSData(){}
  77.     public BoundedSlicesSData(int value, int position){
  78.         this.value = value;
  79.         this.position = position;
  80.     }
  81. }
  82. /*
  83.  * help to sort the BoundedSlicesSData queue
  84.  */
  85. class BoundedSlicesSDataComparator implements Comparator < BoundedSlicesSData>{
  86.     public int compare(BoundedSlicesSData b1, BoundedSlicesSData b2){
  87.         return b1.value – b2.value;
  88.     }
  89. }