Monthly Archives: December 2014

Count bounded slices

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. }

Sort according to another array

Problem:

The input is a sequence x1,x2,…,xn of integers in an arbitrary order, and another sequence a1,a2,..,an of distinct integers from 1 to n (namely a1,a2,…,an is a permutation of 1, 2,…, n). Both sequences are given as arrays. Design an 0(n logn) algorithm to order the first sequence according to the order imposed by the permutation. In other words, for each i, Xi should appear in the position given in ai.

For example, if x = 17, 5, 1,9, and a = 3, 2, 4, 1, then the outcome should be x = 9, 5, 17, 1. The algorithm should be in-place, so you cannot use an additional array.

Take the following analysis:



I use the seq[] to store the position indicating where the element should put. After visited a element i, I change the seq[i] to negative. By checking if the seq[i] is negative, I can know if this element has ever been visited or no.
Code:

  1. public class SortAccordingToAnArray {
  2.     public static void main(String[] args) {
  3.         int[] arr = { 5, 12, 14, 27, 3, 2, 13, 17, 7, 21 };
  4.         int[] index = { 3, 6, 2, 9, 7, 1, 4, 8, 5, 10 };
  5.         System.out.println(“Values: ” + Arrays.toString(arr));
  6.         System.out.println(” Index: ” + Arrays.toString(index));
  7.         putRightPosition(arr, index);
  8.         System.out.println(“Values: ” + Arrays.toString(arr));
  9.     }
  10.     public static void putRightPosition(int[] num, int[] seq){
  11.         for(int i=0;i
  12.             if(seq[i]<0){
  13.                 continue;
  14.             }
  15.             int curr_value = num[i];
  16.             int next_pos = seq[i]-1;
  17.             seq[i] = -seq[i];
  18.             while(true){
  19.                 int tmp = num[next_pos];
  20.                 num[next_pos] = curr_value;
  21.                 curr_value = tmp;
  22.                 tmp = next_pos;
  23.                 next_pos = seq[next_pos]-1;
  24.                 if(next_pos<0){
  25.                     break;
  26.                 }
  27.                 seq[tmp] = -seq[tmp];
  28.             }//while
  29.         }//for
  30.     }
  31. }

Crack razzle adventure game – dfs, backtrack implementation

My mother-in-law likes a game in ipad. It is called Ruzzle Adventure. The idea is to find the word in a letter matrix. The longer the word is, the higher score you will have. For example, in the following letter arrays, you can find a ‘gates’ word.

Today, I think of cracking this game, find the potiential words it has.

The idea is to traverse each letter to its neighbor, go on and on, and see what word it can reach. And design a dictionary, get word from the dictionary.

I define some parameters to help.
puzzleCharArray[][], stores the characters of the puzzle game:

  1.     public static char[][] puzzleCharArrzy = {
  2.         {‘s’, ‘t’, ‘s’, ‘t’},
  3.         {‘w’, ‘o’, ‘p’, ‘h’},
  4.         {‘h’, ‘r’, ‘e’, ‘t’},
  5.         {‘a’, ‘d’, ‘t’, ‘o’}
  6.     };

stepHis[][], is to avoid duplicately visit to a puzzle letter. When I do backtrack, this stores what letters has already visited.

The most important is the dfs function. The boundary of it includes:
1. the (x,y) position should be within the array. i.e. can’t go to (-1,0)
2. The visited (x,y) shouldn’t be visited for 2nd time, which is helped by stepHis[][]
The return policies are:
If the current word is not found, then return.
If the current word is a prefix of a word, go on searching its neighbor.
If the current word is found in dictionary, add it to result list, and go on searching its neighbor.
The dfs code and comments are showed below:

  1.     /*
  2.      * Use dfs to find the possible word. Save the result in ArrayList result.
  3.      * (x,y) indicate the current position in charPuzzle
  4.      */
  5.     public static void dfsWord(String word, int wordPos, int x, int y, boolean[][] stepHis, ArrayList result){
  6.         if(x<0||x>=puzzleCharArrzy.length||y<0||y>=puzzleCharArrzy[0].length||stepHis[x][y]==true){
  7.             return;    //if (x,y) is in wrong position, or (x,y) is already traversed before, then return.
  8.         }
  9.         stepHis[x][y] = true;    //mark this (x,y) as traversed.
  10.         String currWord = word.substring(0, wordPos) + puzzleCharArrzy[x][y];    //update the current word
  11.         int foundResult = searchWord(currWord);    //find find in dictionary
  12.         if(foundResult==NOT_FOUND){    //not found, then return
  13.             stepHis[x][y] = false;
  14.             return;
  15.         }
  16.         if(foundResult==WORD_FOUND&&wordPos!=0){
  17.             result.add(currWord);    //if found, then add to result list. Besides, it can go on finding the larger word
  18.         }
  19.         dfsWord(currWord, wordPos+1, x-1, y-1, stepHis, result);
  20.         dfsWord(currWord, wordPos+1, x-1, y, stepHis, result);
  21.         dfsWord(currWord, wordPos+1, x-1, y+1, stepHis, result);
  22.         dfsWord(currWord, wordPos+1, x, y-1, stepHis, result);
  23.         dfsWord(currWord, wordPos+1, x, y+1, stepHis, result);
  24.         dfsWord(currWord, wordPos+1, x+1, y-1, stepHis, result);
  25.         dfsWord(currWord, wordPos+1, x+1, y, stepHis, result);
  26.         dfsWord(currWord, wordPos+1, x+1, y+1, stepHis, result);
  27.         stepHis[x][y] = false;    //unmark the step.
  28.     }

Design the dictionary. Read the dictionary into a String[] array. Design a searchWord() function to check is a word is in the dictionary. The return result can be 3 types:
int WORD_FOUND=1, the word is in the dictionary.
int NOT_FOUNC=2, the word doesn’t exist in dictionary.
int PREFIX_FOUND=0, the word is a prefix of a certain word in the dictionary. For example, ‘appl’ is a prefix of ‘apple’.

I downloaded a txt file dictionary. It has alphebatic order. Load the dictionary to the String[].

The result is like below.
Input array:
public static char[][] puzzleCharArrzy = {
{‘s’, ‘t’, ‘s’, ‘t’},
{‘w’, ‘o’, ‘p’, ‘h’},
{‘h’, ‘r’, ‘e’, ‘t’},
{‘a’, ‘d’, ‘t’, ‘o’}
};

Output of top 10:
potsherd
sported
stored
sorted
stored
sorted
spored
whored
posher
ported

The complete code is here:

  1. package wordpuzzle;
  2. import java.io.BufferedReader;
  3. import java.io.FileReader;
  4. import java.util.ArrayList;
  5. import java.util.Collections;
  6. import java.util.Comparator;
  7. public class WordUtil {
  8.     public static String[] dict;
  9.     public static final int DICT_LENGTH = 109583; //the word length of the dictionary
  10.     public static final String DICT_PATH = “C:/Users/lipeng/Work Space/WordPuzzle/wordsEn.txt”;
  11.     public static final int PREFIX_FOUND = 0;
  12.     public static final int WORD_FOUND = 1;
  13.     public static final int NOT_FOUND = 2;
  14.     public static final String puzzleChars = “hahalritudeanreutkdepdvit”;
  15.     public static final int puzzleLen = 5;
  16.     public static char[][] puzzleCharArrzy = {
  17.         {‘s’, ‘t’, ‘s’, ‘t’},
  18.         {‘w’, ‘o’, ‘p’, ‘h’},
  19.         {‘h’, ‘r’, ‘e’, ‘t’},
  20.         {‘a’, ‘d’, ‘t’, ‘o’}
  21.     };
  22.     public static void main(String[] args) {
  23.         WordUtil.Init();
  24.         ArrayList result = findWord();
  25.         result = arraySort(result);
  26.         printTop10(result);
  27.     }
  28.     /*
  29.      * sort the result descend
  30.      */
  31.     public static ArrayList arraySort(ArrayList result){
  32.         ArrayList returnResult = new ArrayList();
  33.         while(!result.isEmpty()){
  34.             int maxPos = -1;
  35.             int maxLen = Integer.MIN_VALUE;
  36.             String curr;
  37.             for(int i=0;i < result.size();i++){
  38.                 curr = result.get(i);
  39.                 if(curr.length()>maxLen){
  40.                     maxLen = curr.length();
  41.                     maxPos = i;
  42.                 }
  43.             }
  44.             curr = result.remove(maxPos);
  45.             returnResult.add(curr);
  46.         }
  47.         return returnResult;
  48.     }
  49.     public static void printResult(ArrayList result){
  50.         for(int i=0;i < result.size();i++){
  51.             System.out.println(result.get(i));
  52.         }
  53.     }
  54.     /*
  55.      * print the top 10 result
  56.      */
  57.     public static void printTop10(ArrayList result){
  58.         for(int i=0;i
  59.             System.out.println(result.get(i));
  60.         }
  61.     }
  62.     /*
  63.      * traverse all the position, try to find the word.
  64.      * Use stepHis to record if a position has been traversed before.
  65.      */
  66.     public static ArrayList findWord(){
  67.         boolean[][] stepHis = new boolean[puzzleCharArrzy.length][puzzleCharArrzy[0].length];
  68.         ArrayList result = new ArrayList();
  69.         for(int i=0;i < puzzleCharArrzy.length;i++){
  70.             for(int j=0;j < puzzleCharArrzy[0].length;j++){
  71.                 dfsWord(“”, 0, i, j, stepHis, result);
  72.             }
  73.         }
  74.         return result;
  75.     }
  76.     /*
  77.      * Use dfs to find the possible word. Save the result in ArrayList result.
  78.      * (x,y) indicate the current position in charPuzzle
  79.      */
  80.     public static void dfsWord(String word, int wordPos, int x, int y, boolean[][] stepHis, ArrayList result){
  81.         if(x<0||x>=puzzleCharArrzy.length||y<0||y>=puzzleCharArrzy[0].length||stepHis[x][y]==true){
  82.             return;    //if (x,y) is in wrong position, or (x,y) is already traversed before, then return.
  83.         }
  84.         stepHis[x][y] = true;    //mark this (x,y) as traversed.
  85.         String currWord = word.substring(0, wordPos) + puzzleCharArrzy[x][y];    //update the current word
  86.         int foundResult = searchWord(currWord);    //find find in dictionary
  87.         if(foundResult==NOT_FOUND){    //not found, then return
  88.             stepHis[x][y] = false;
  89.             return;
  90.         }
  91.         if(foundResult==WORD_FOUND&&wordPos!=0){
  92.             result.add(currWord);    //if found, then add to result list. Besides, it can go on finding the larger word
  93.         }
  94.         dfsWord(currWord, wordPos+1, x-1, y-1, stepHis, result);
  95.         dfsWord(currWord, wordPos+1, x-1, y, stepHis, result);
  96.         dfsWord(currWord, wordPos+1, x-1, y+1, stepHis, result);
  97.         dfsWord(currWord, wordPos+1, x, y-1, stepHis, result);
  98.         dfsWord(currWord, wordPos+1, x, y+1, stepHis, result);
  99.         dfsWord(currWord, wordPos+1, x+1, y-1, stepHis, result);
  100.         dfsWord(currWord, wordPos+1, x+1, y, stepHis, result);
  101.         dfsWord(currWord, wordPos+1, x+1, y+1, stepHis, result);
  102.         stepHis[x][y] = false;    //unmark the step.
  103.     }
  104.     public static int searchWord(String word){
  105.         return binarySearch(word, 0, DICT_LENGTH-1);
  106.     }
  107.     /*
  108.      * use binarysearch to find the word in the dict.
  109.      */
  110.     public static int binarySearch(String word, int start, int end){
  111.         if(start>end){    //time to result result
  112.             if(dict[start].length()>=word.length()&&dict[start].subSequence(0, word.length()).equals(word)){
  113.                 return PREFIX_FOUND;    //the word is a part of word in dict. it can still go on searching
  114.             }
  115.             if(dict[end].length()>=word.length()&&dict[end].subSequence(0, word.length()).equals(word)){
  116.                 return PREFIX_FOUND;    //the word is a part of word in dict. it can still go on searching
  117.             }
  118.             return NOT_FOUND;
  119.         }
  120.         int mid = (start+end)/2;
  121.         int cmp = dict[mid].compareTo(word);
  122.         if(cmp<0){
  123.             return binarySearch(word, mid+1, end);
  124.         }
  125.         else if(cmp>0){
  126.             return binarySearch(word, start, mid-1);
  127.         }
  128.         else{
  129.             return WORD_FOUND;
  130.         }
  131.     }
  132.     public static void Init(){
  133.         dict = readFile(DICT_PATH);
  134.     }
  135.     /*
  136.      * to initial the puzzleChar by inputting a string.
  137.      */
  138.     public static void Init2(){
  139.         puzzleCharArrzy = new char[puzzleLen][puzzleLen];
  140.         for(int i=0;i<  puzzleLen;i++){
  141.             for(int j=0;j < puzzleLen;j++){
  142.                 puzzleCharArrzy[i][j] = puzzleChars.charAt(puzzleLen*i+j);
  143.             }
  144.         }
  145.         dict = readFile(DICT_PATH);
  146.     }
  147.     /*
  148.      * read the dict file from dict.txt
  149.      */
  150.     public static String[] readFile(String file){
  151.         String[] dict = new String[DICT_LENGTH];
  152.         try{
  153.             BufferedReader br = new BufferedReader(new FileReader(file));
  154.             String line;
  155.             int i=0;
  156.             while ((line = br.readLine()) != null) {
  157.                 dict[i] = line;
  158.                 i++;
  159.             }
  160.             br.close();
  161.         }catch(Exception e){
  162.             e.printStackTrace();
  163.         }
  164.         return dict;
  165.     }
  166. }

download the dictionary here: link

Partition an array by an uncertain pivot, only by one trip

Toady, I read about bolts and nuts problem. The method is similar to quicksort. But one difference is that, we should partition the array by an uncertain pivot. It means we don’t know where the pivot is in the array.
The normal way should be traverse the array for one time, and found the position of pivot. Then do quicksort as usual. By that, it can finish it in O(n) time, yet with traversal on the array for 2 times.

But I believe there is way that it only traverse for one time. After done hours research, I found this method. Which I should thank kartik kukreja for providing me this idea, link. By this method, we can finish it by one trip on the array.

The idea is that we keep a ‘higher group’ in the traversal, which means those elements which are larger than the pivot. And we record the start position of the ‘higher group’. Let me take an example:
Assume we want to partition the following array by a pivot of 5. If current array is:
3 9 7 6 2 1 5 4 8
Always maintain the ‘higher group’ in the one trip.
Next, we need to judge 2. Since 2 is less than 5, so we swap 2 with the first element of the higher group. So the next array is:
3 2 7 6 9 1 5 4 8
By this, higher group moves forward by 1. We should record the 1st element position in higher group.
Then next:
3 2 1 6 9 7 5 4 8
When we encounter the pivot 5, we swap it with the last element. So the next is:
3 2 1 6 9 7 8 4 5
After we’ve done with 2nd to last element, it is like this:
3 2 1 4 9 7 8 6 5
Now, we swap the last element(pivot) with 1st element position in higher group. The final result would be:
3 2 1 4 5 7 8 6 

This is the code:

public static int partition(int[] arr, int low, int high, int pivot) {
    int i = low;
    for (int j = low; j < high; j++) {
        if (arr[j] < pivot){
            swap(arr, i, j);
            i++;
        } else if(arr[j] == pivot){
            swap(arr, j, high);
            j--;
        }
    }
    swap(arr, i, high);
    return i;
}
public static void swap(int[] nums, int i, int j) {
    int tmp = nums[i];
    nums[i] = nums[j];
    nums[j] = tmp;
}

Find median or Kth number in 2 sorted array

Problem
The idea of the solution is very easy: use binary search. But when I wrote it, it took me a long time to verify the code.
For example, find the 4th number from a=[2, 4, 6, 8] and b=[5,9]
The result should be 6.

Solution

Basic idea:
a=[0,…,a_start, …, a_mid,…,a_end,…,a.length-1]
b=[0,…,b_start, …, b_mid,…,b_end,…,b.length-1]
Let half_length be number of element in a[a_start,…,a_mid] and b[b_start,…,b_mid].
find the kth from a and b.
Assume a[a_mid] is larger than b[b_mid].
If k < half_length, then we know that kth number can’t be in higher part of a, a[a_mid,…,a_end]. So next, we search a[a_start,…,a_mid-1] and b[b_start,…,b_end]
If k>=half_length, then we know that kth number can’t be in lower part of b, b[b_start,…,b_mid]. So next, we search a[a_start, a_end] and b[b_mid+1,…,b_end]. Meanwhile, we should set new value to k. k=k-(b_mid-b_start+1)

Return result when:
if(a_start>a_end){
return b[b_start+k-1];
}
if(b_start>b_end){
return a[a_start+k-1];
}

Case analysis1

a[a_mid]
half_length = 3
k>=half_length, so cut off lower part of a[], and k should deduct 2, which is 1, 3

1

b[] is out of bound, return a[a_s+k-1], which is 5

Case analysis2

a[a_mid]>b[b_mid]
half_length = 5
k>=half_length, so cut off lower part of b[], and k should deduct 3, which is 2, 4

a[a_mid]half_length = 4
k

b[] is out of bound, return a[a_s+k-1]=a[0+3-1], which is 5

My code is below:

  1. public class MedianIn2SortedArray {
  2.     public static void main(String[] args) {
  3.         int[] a = {1,3,5,9,10};
  4.         int[] b = {2,4,6,8};
  5.         int median = findMedian(a,b);
  6.         System.out.println(median);
  7.     }
  8.     public static int findMedian(int[] a, int[] b){
  9.         int k = (a.length + b.length)/2;
  10.         return findK(a, b, k, 0, a.length-1, 0, b.length-1);
  11.     }
  12.     public static int findK(int[] a, int[] b, int k, int a_start, int a_end, int b_start, int b_end){
  13.         if(a_start>a_end){
  14.             return b[b_start+k-1];
  15.         }
  16.         if(b_start>b_end){
  17.             return a[a_start+k-1];
  18.         }
  19.         int a_mid = a_start+(a_end-a_start)/2;
  20.         int b_mid = b_start+(b_end-b_start)/2;
  21.         int half_len = a_mid-a_start+b_mid-b_start+2;
  22.         if(a[a_mid]>b[b_mid]){
  23.             if(k
  24.                 //cut off the high part of large array, which is high of a[]
  25.                 return findK(a, b, k, a_start, a_mid-1, b_start, b_end);
  26.             }
  27.             else{
  28.                 //cut off the low part of small array, which is low of b[]
  29.                 return findK(a, b, k-(b_mid-b_start+1),a_start, a_end, b_mid+1, b_end);
  30.             }
  31.         }
  32.         else{
  33.             if(k
  34.                 //cut off the high part of large array, which is high of b[]
  35.                 return findK(a, b, k, a_start, a_end, b_start, b_mid-1);
  36.             }
  37.             else{
  38.                 //cut off the low part of small array, which is low of a[]
  39.                 return findK(a, b, k-(a_mid-a_start+1), a_mid+1, a_end, b_start, b_end);
  40.             }
  41.         }
  42.     }
  43. }

Balance server capacity

Problem description:
There are at most eight servers in a data center. Each server has got a capacity/memory limit. There can be at most 8 tasks that need to be scheduled on those servers. Each task requires certain capacity/memory to run, and each server can handle multiple tasks as long as the capacity limit is not hit. Write a program to see if all of the given tasks can be scheduled or not on the servers?

Ex:
Servers capacity limits: 8, 16, 8, 32
Tasks capacity needs: 18, 4, 8, 4, 6, 6, 8, 8
For this example, the program should say ‘true’.

Ex2:
Server capacity limits: 1, 3
Task capacity needs: 4
For this example, program should return false.

Solution:
First impression would be using greedy algorith. Each time, put the max task in the max capacity server. But it won’t find the best answer for a lot of times. An counter-example is: Server capacity [4, 3], task[3, 2, 2].

So the solution should be use recursion to traverse the whole result possibilities. The sample code is following. It is a easy recursion case, no comment :)

  1. public class ServerCapacityBalancer {
  2.     public static void main(String[] args) {
  3.         int[] server = {8, 16, 8, 32};
  4.         int[] task = {18,8,8,8,6,6,4,4};
  5.         int[] result = balanceServer(server, task);
  6.         System.out.println(Arrays.toString(result));
  7.     }
  8.     public static int[] balanceServer(int[] server, int[] task){
  9.         if(server==null||task==null){
  10.             return null;
  11.         }
  12.         int[] result = new int[task.length];
  13.         for(int i=0;i
  14.             result[i] = -1;
  15.         }
  16.         balanceServerUtil(server, task, 0, result);
  17.         return result;
  18.     }
  19.     //put task[n] in the server, and save the result
  20.     public static boolean balanceServerUtil(int[] server, int[] task, int n, int[] result){
  21.         if(n>=task.length){
  22.             return true;
  23.         }
  24.         for(int i=0;i
  25.             if(server[i]>=task[n]){
  26.                 server[i] -= task[n];
  27.                 result[n] = i;
  28.                 if(balanceServerUtil(server, task, n+1, result)){
  29.                     return true;
  30.                 }
  31.                 server[i] += task[n];
  32.                 result[n] = -1;
  33.             }
  34.         }
  35.         return false;
  36.     }
  37. }

Find median out of 5 numbers

In quickselect, it requires to find the median out of the group of 5 numbers. Here I found a way from stackoverflow link. It requires 6 comparisons.

  1. Start a mergesort with the first 4 elements and order each pair (2 comparisons)
  2. Compare the two lower ones of each pair and eliminate the lowest one from the possibilities (3 comparisons)
  3. Add in the 5th number set aside to the number without a pair and compare the two (4 comparisons)
  4. Compare the two lowest of the two new pairs and eliminate the lower one (5 comparisons)
  5. Compare the one by itself and the lower of the last pair and the lower number is the medianThe possible median is within the parentesis

Find the closest leaf in a Binary Tree

Problem description:
Given a Binary Tree and a key ‘k’, find distance of the closest leaf from ‘k’.

              A
            /    \    
           B       C
                 /   \  
                E     F   
               /       \
              G         H
             / \       /
            I   J     K
Closest key to 'H' is 'K', so distance is 1 for 'H'
Closest key to 'C' is 'B', so distance is 2 for 'C'
Closest key to 'E' is either 'I' or 'J', so distance is 2 for 'E' 
Closest key to 'B' is 'B' itself, so distance is 0 for 'B'

Solution:
Find all the ancestry of the target node, and the min-depth of them. Distance from target to its ancestry, plus distance from ancestry to ancestry’s min-depth leaf is a potential result. Among them and the min-depth of the target node itself, find the smallest one.

The traversal process is:
For each node, it traverse the left and right sub-tree, and get the min-depth from each sub-tree. And it will return min-depth to its ancestry.
After traverse each sub-tree, if it found the target in either sub-tree, this node is treated as an ancestry of the target node. And the ancestry information should be stored.

In my code, I define a AncestryInfo class, to restore the ancestry information:
class AncestryInfo{
int[] ancestry_record;    //records the ancestry nodes from target node. Target node is also included in position 0;
int[] ancestry_level;    //records the min deep of ancestry nodes.
int[] leaf;        //records the leaf which the ancestry nodes reach to the min deep
}

  1. public class FindNearestLeaf {
  2.     public static void main(String[] args) {
  3.         Tree tree = Tree.getTree();
  4.         findNearestLeaf(tree, 7);
  5.         System.out.println();
  6.     }
  7.     public static void findNearestLeaf(Tree tree, int value){
  8.         AncestryInfo ancestry = new AncestryInfo();
  9.         //traverse the tree, to find the relative information
  10.         findNearestLeafUtil(tree, value, ancestry, new MyInteger(), new MyInteger(), new MyBoolean());
  11.         int leaf = ancestry.leaf[0];
  12.         int distance = ancestry.ancestry_level[0];
  13.         for(int i=1;i
  14.             if(i-0+ancestry.ancestry_level[i]
  15.                 distance = i-0+ancestry.ancestry_level[i];
  16.                 leaf = ancestry.leaf[i];
  17.             }
  18.         }
  19.         distance–;
  20.         System.out.println(“Nearest Leaf:” + leaf + “\tDistance:” + distance);
  21.     }
  22.     public static void findNearestLeafUtil(Tree root, int value, AncestryInfo anc, MyInteger depth, MyInteger leaf, MyBoolean found){
  23.         if(root==null){
  24.             return;
  25.         }
  26.         MyInteger l_depth = new MyInteger(Integer.MAX_VALUE);
  27.         MyInteger r_depth = new MyInteger(Integer.MAX_VALUE);
  28.         MyBoolean l_found = new MyBoolean();
  29.         MyBoolean r_found = new MyBoolean();
  30.         MyInteger l_leaf = new MyInteger();
  31.         MyInteger r_leaf = new MyInteger();
  32.         if(root.left!=null){
  33.             findNearestLeafUtil(root.left, value, anc, l_depth, l_leaf, l_found);
  34.         }
  35.         if(root.right!=null){
  36.             findNearestLeafUtil(root.right, value, anc, r_depth, r_leaf, r_found);
  37.         }
  38.         if(root.left==null&&root.right==null){    // current node is a leaf
  39.             depth.i = 1;
  40.             leaf.i = root.value;
  41.         }
  42.         else{    //if current node is not a leaf, get the depth from information of 2 sub tress.
  43.             depth.i = Math.min(l_depth.i, r_depth.i) + 1;
  44.             leaf.i = l_depth.i
  45.         }
  46.         found.bool = l_found.bool||r_found.bool;
  47.         if(found.bool){
  48.             //if the target node is already found, then current node is treated as an ancestry. So store the ancestry information.
  49.             anc.ancestry_record = Arrays.copyOf(anc.ancestry_record, anc.ancestry_record.length+1);
  50.             anc.ancestry_record[anc.ancestry_record.length-1] = root.value;
  51.             anc.ancestry_level = Arrays.copyOf(anc.ancestry_level, anc.ancestry_level.length+1);
  52.             anc.ancestry_level[anc.ancestry_level.length-1] = depth.i;
  53.             anc.leaf = Arrays.copyOf(anc.leaf, anc.leaf.length+1);
  54.             anc.leaf[anc.leaf.length-1] = leaf.i;
  55.             return;
  56.         }
  57.         if(root.value==value){    //current node is the target, initial the ancestry information
  58.             found.bool = true;
  59.             anc.ancestry_record = new int[]{root.value};
  60.             anc.ancestry_level = new int[]{depth.i};
  61.             anc.leaf = new int[]{leaf.i};
  62.             return;
  63.         }
  64.         return;
  65.     }
  66. }
  67. class AncestryInfo{
  68.     int[] ancestry_record;    //records the ancestry nodes from target node. Target node is also included in position 0;
  69.     int[] ancestry_level;    //records the min deep of ancestry nodes.
  70.     int[] leaf;        //records the leaf which the ancestry nodes reach to the min deep
  71. }
  72. class MyBoolean {
  73.     public boolean bool;
  74.     public MyBoolean(boolean bool){
  75.         this.bool = bool;
  76.     }
  77.     public MyBoolean(){
  78.         this.bool = false;
  79.     }
  80.     public String toString(){
  81.         return String.valueOf(bool);
  82.     }
  83. }
  84. class MyInteger{
  85.     public int i = 0;
  86.     public MyInteger(int i){
  87.         this.i = i;
  88.     }
  89.     public MyInteger(){}
  90.     public String toString(){
  91.         return String.valueOf(i);
  92.     }
  93. }
  94. class Tree{
  95.     public Tree(int value){
  96.         this.value = value;
  97.     }
  98.     public Tree(String value){
  99.         this.valueString = value;
  100.     }
  101.     public Tree left;
  102.     public Tree right;
  103.     public int value;
  104.     public String valueString;
  105.     public static Tree getTree(){
  106.         Tree t18 = new Tree(18);
  107.         Tree t17 = new Tree(17);
  108.         Tree t16 = new Tree(16);
  109.         Tree t15 = new Tree(15);
  110.         Tree t14 = new Tree(14);
  111.         Tree t13 = new Tree(13);
  112.         Tree t12 = new Tree(12);
  113.         Tree t11 = new Tree(11);
  114.         Tree t10 = new Tree(10);
  115.         Tree t9 = new Tree(9);
  116.         Tree t8 = new Tree(8);
  117.         Tree t7 = new Tree(7);
  118.         Tree t6 = new Tree(6);
  119.         Tree t5 = new Tree(5);
  120.         Tree t4 = new Tree(4);
  121.         Tree t3 = new Tree(3);
  122.         Tree t2 = new Tree(2);
  123.         Tree t1 = new Tree(1);
  124.         t8.left = t9;
  125.         t6.left = t8;
  126.         t5.right = t7;
  127.         t4.left = t5;
  128.         t4.right = t6;
  129.         t2.left = t4;
  130.         t1.left = t2;
  131.         t1.right = t3;
  132.         t6.right = t10;
  133.         t3.left = t11;
  134.         t3.right = t12;
  135.         t12.left = t13;
  136.         t12.right = t14;
  137.         t13.left = t15;
  138.         t13.right = t16;
  139.         t16.right = t17;
  140.         t17.right = t18;
  141.         return t1;
  142.     }
  143. }

Patricia Tree

In the structure of my PatriciaTree, it has following parameters:
char c, indicate the char the node has.
HashMap<Character, PatriciaTree> children, indicate the children the node has.
String leftString, this a bit difficult to explain. So let me raise an example. If root only has a word “dog”. So the structure would be like:
.root…….
..\………
…d(og)….
But not:
.root…….
..\………
…d……..
….\…….
…..o……
……\…..
…….g….
So, in this case, I use the leftString to store the string after ‘d’, which is ‘og’. And I call the node d(og) string leaf.

is that I define 4 types of nodes:
1. STATE_ROOT, the root the patricia tree.
2. STATE_STRINGLEAF, it is a leaf, and it has left string in it. Like the example I showed above.
3. STATE_LEAF, it is a leaf, and it doesn’t has left string.
For example, the ‘g’ and ‘t’ nodes are both LEAF node, but not string leaf node.
.root………
..\………..
…d……….
….\………
…..o……..
…../.\…….
…g….t…..
4. STATE_MIDDLE, in the above case, the ‘d’ and ‘o’ are middle nodes.

In the following code. it demonstrate how to build a patricia tree, and the method to find if a word exists in a patricia tree.

  1. import java.util.HashMap;
  2. public class PatriciaTree {
  3.     public static final int STATE_ROOT = 0;
  4.     public static final int STATE_LEAF = 1;
  5.     public static final int STATE_STRINGLEAF = 2;
  6.     public static final int STATE_MIDDLE = 3;
  7.     char c;
  8.     HashMap<Character, PatriciaTree> children;
  9.     int state;    //0 is root, 1 is leaf, 2 is leaf with string, 3 is middle
  10.     String leftString;    //if the node is leaf with string, it has a rest word
  11.     PatriciaTree parent;
  12.     //store word into this PatriciaTree, word starts from pos
  13.     public boolean addNode(String word, int pos, PatriciaTree parent){
  14.         if(word==null||pos>=word.length()){
  15.             return false;
  16.         }
  17.         PatriciaTree child;
  18.         if(state==STATE_ROOT||state==STATE_MIDDLE){
  19.             //if it is root, then find if it children have tree with character pos[0]
  20.             child = children.get(word.charAt(pos));
  21.             if(child==null){    //it doesn’t has word.charAt[pos], then create tree under it.
  22.                 child = new PatriciaTree(word, pos, this);
  23.                 children.put(word.charAt(pos), child);
  24.                 return true;
  25.             }
  26.             return child.addNode(word, pos+1, this);    //it has char, then create tree under its child.
  27.         }
  28.         if(state==STATE_LEAF){
  29.             //now it is leaf, and there is still chars, then just change it to a STRINGLEAF
  30.             this.state = STATE_STRINGLEAF;
  31.             this.leftString = word.substring(pos, word.length()-1);
  32.             return true;
  33.         }
  34.         if(state==STATE_STRINGLEAF){
  35.             if(word.charAt(pos)!=leftString.charAt(0)){
  36.                 //1st char of leftString doesn’t match word[pos], so create the tree under it.
  37.                 //And create leftString as its subtree.
  38.                 child = new PatriciaTree(word, pos, this);
  39.                 children.put(word.charAt(pos), child);
  40.                 child = new PatriciaTree(leftString, 0, this);
  41.                 children.put(leftString.charAt(0), child);
  42.                 this.state = STATE_MIDDLE;
  43.                 return true;
  44.             }
  45.             //1st char of leftString match word[pos], so break the stringleaf into middle,
  46.             //and create its child with char of the 1st leftString
  47.             this.state = STATE_MIDDLE;
  48.             child = new PatriciaTree(leftString, 0, this);
  49.             children.put(leftString.charAt(0), child);
  50.             this.leftString = “”;
  51.             child.addNode(word, pos+1, child);
  52.             return true;
  53.         }
  54.         return false;
  55.     }
  56.     public boolean findString(String word, int pos){
  57.         if(pos>=word.length()){
  58.             if(this.state==STATE_MIDDLE){
  59.                 return false;    //is in the middle, is not counted as found.
  60.             }
  61.             if(this.state==STATE_LEAF){
  62.                 return true;    //return true if this is leaf
  63.             }
  64.             return false;
  65.         }
  66.         PatriciaTree child;
  67.         if(this.state==STATE_ROOT||this.state==STATE_MIDDLE){
  68.             child = this.children.get(word.charAt(pos));
  69.             return child==null?false:child.findString(word, pos+1);
  70.         }
  71.         if(this.state==STATE_LEAF){
  72.             return false;    //the word is larger than the leaf string
  73.         }
  74.         if(this.state==STATE_STRINGLEAF){
  75.             String strInWord = word.substring(pos, word.length());
  76.             if(leftString.equals(strInWord)){
  77.                 return true;
  78.             }
  79.         }
  80.         return false;
  81.     }
  82.     public PatriciaTree(){
  83.         this.children = new HashMap<Character, PatriciaTree>();
  84.     }
  85.     public PatriciaTree(String word, int pos, PatriciaTree parent){
  86.         this.c = word.charAt(pos);
  87.         this.parent = parent;
  88.         this.state = STATE_LEAF;
  89.         this.children = new HashMap<Character, PatriciaTree>();
  90.         if(pos<word.length()-1){
  91.             this.state = STATE_STRINGLEAF;
  92.             this.leftString = word.substring(pos+1, word.length());
  93.         }
  94.     }
  95.     public static void main(String[] args) {
  96.         PatriciaTree root = new PatriciaTree();
  97.         root.state = STATE_ROOT;
  98.         String[] words = {“zebra”, “zero”, “dog”, “dot”, “ducks”, “duh”, “ducky”};
  99.         for(int i=0;i<words.length;i++){
  100.             root.addNode(words[i], 0, root);
  101.         }
  102.         System.out.println(root.findString(“dogg”, 0));
  103.     }
  104. }

Find weighted median in matrix

Evolve the problem to 2-dimension array.
There is a matrix, m x n. Several groups of people locate at some certain spots. In the following example, there are three groups and the number 4 indicates there are four people in this group. Now we want to find a meeting point in the matrix so that the cost of all groups moving to that point is the minimum.

The solution is that find the weighted median from x and y direction.
For example, the matrix is as follow:

Then, the sequence in x direction is 4 3 1 6 5, the sequence in y direction is 7 4 5 3. We find the weighted median both in x and y direction.

For the sequence 7 4 5 3, we think like this, there are 4 cities in a line, which continuously locate at 1, 2, 3, 4. The weight of them are 7, 4, 5, 3.
So the sequence is 1 1 1 1 1 1 1 2 2 2 2 3 3 3 3 3 4 4 4. So the median is 10th , which is 2, which symbolizes 4. By the same way, we can find the 10th element in 4 3 1 6 5 exists in 6. So the weighted median is array[3][1].