Sort Colors II
原題鏈接: http://lintcode.com/zh-cn/problem/sort-colors-ii/#
Given an array of n objects with k different colors (numbered from 1 to k), sort them so that objects of the same color are adjacent, with the colors in the order 1, 2, ... k.
You are not suppose to use the library's sort function for this problem.
GIven colors=[3, 2, 2, 1, 4], k=4, your code should sort colors in-place to [1, 2, 2, 3, 4].
A rather straight forward solution is a two-pass algorithm using counting sort. That will cost O(k) extra memory.
Can you do it without using extra memory?
SOLUTION 1:
使用快排,時間復雜度是O(nlogn),空間復雜度是O(Log(N))

1 /** 2 * @param colors: A list of integer 3 * @param k: An integer 4 * @return: nothing 5 */ 6 /* 7 Solution 1: Using the quick sort. 8 */ 9 public void sortKColors1(int[] colors, int k) { 10 // write your code here 11 if (colors == null) { 12 return; 13 } 14 15 quickSort(colors, 0, colors.length - 1); 16 } 17 18 public void quickSort(int[] colors, int left, int right) { 19 if (left >= right) { 20 return; 21 } 22 23 int pivot = colors[right]; 24 25 int pos = partition(colors, left, right, pivot); 26 27 quickSort(colors, left, pos - 1); 28 quickSort(colors, pos + 1, right); 29 } 30 31 public int partition(int[] colors, int left, int right, int pivot) { 32 int leftPoint = left - 1; 33 int rightPoint = right; 34 35 while (true) { 36 while (colors[++leftPoint] < pivot); 37 38 while (leftPoint < rightPoint && colors[--rightPoint] > pivot); 39 40 if (leftPoint >= rightPoint) { 41 break; 42 } 43 44 swap(colors, leftPoint, rightPoint); 45 } 46 47 swap(colors, leftPoint, right); 48 return leftPoint; 49 } 50 51 public void swap(int[] colors, int left, int right) { 52 int tmp = colors[left]; 53 colors[left] = colors[right]; 54 colors[right] = tmp; 55 }
SOLUTION 2:
inplace,並且O(N)時間復雜度的算法。
我們可以使用類似桶排序的思想,對所有的數進行計數。
1. 從左掃描到右邊,遇到一個數字,先找到對應的bucket.比如
3 2 2 1 4
第一個3對應的bucket是index = 2 (bucket從0開始計算)
2. Bucket 如果有數字,則把這個數字移動到i的position(就是存放起來),然后把bucket記為-1(表示該位置是一個計數器,計1)。
3. Bucket 存的是負數,表示這個bucket已經是計數器,直接減1. 並把color[i] 設置為0 (表示此處已經計算過)
4. Bucket 存的是0,與3一樣處理,將bucket設置為-1, 並把color[i] 設置為0 (表示此處已經計算過)
5. 回到position i,再判斷此處是否為0(只要不是為0,就一直重復2-4的步驟)。
6.完成1-5的步驟后,從尾部到頭部將數組置結果。(從尾至頭是為了避免開頭的計數器被覆蓋)
例子(按以上步驟運算):
3 2 2 1 4
2 2 -1 1 4
2 -1 -1 1 4
0 -2 -1 1 4
-1 -2 -1 0 4
-1 -2 -1 -1 0

1 // Solution 2: inplace, O(n) 2 public void sortKColors(int[] colors, int k) { 3 // write your code here 4 if (colors == null) { 5 return; 6 } 7 8 int len = colors.length; 9 for (int i = 0; i < len; i++) { 10 // Means need to deal with A[i] 11 while (colors[i] > 0) { 12 int num = colors[i]; 13 if (colors[num - 1] > 0) { 14 // 1. There is a number in the bucket, 15 // Store the number in the bucket in position i; 16 colors[i] = colors[num - 1]; 17 colors[num - 1] = -1; 18 } else if (colors[num - 1] <= 0) { 19 // 2. Bucket is using or the bucket is empty. 20 colors[num - 1]--; 21 // delete the A[i]; 22 colors[i] = 0; 23 } 24 } 25 } 26 27 int index = len - 1; 28 for (int i = k - 1; i >= 0; i--) { 29 int cnt = -colors[i]; 30 31 // Empty number. 32 if (cnt == 0) { 33 continue; 34 } 35 36 while (cnt > 0) { 37 colors[index--] = i + 1; 38 cnt--; 39 } 40 }
GITHUB:
https://github.com/yuzhangcmu/LeetCode_algorithm/blob/master/lintcode/array/SortKColors.java