leetcode-75-顏色分類(sort colors)-java
阿新 • • 發佈:2018-12-29
題目及測試
package pid075; /*顏色分類 給定一個包含紅色、白色和藍色,一共 n 個元素的陣列,原地對它們進行排序,使得相同顏色的元素相鄰,並按照紅色、白色、藍色順序排列。 此題中,我們使用整數 0、 1 和 2 分別表示紅色、白色和藍色。 注意: 不能使用程式碼庫中的排序函式來解決這道題。 示例: 輸入: [2,0,2,1,1,0] 輸出: [0,0,1,1,2,2] 進階: 一個直觀的解決方案是使用計數排序的兩趟掃描演算法。 首先,迭代計算出0、1 和 2 元素的個數,然後按照0、1、2的排序,重寫當前陣列。 你能想出一個僅使用常數空間的一趟掃描演算法嗎? */ public class main { public static void main(String[] args) { int[] testTable = {2,0,2,1,1,0}; test(testTable); } private static void test(int[] ito) { Solution solution = new Solution(); int rtn; long begin = System.currentTimeMillis(); System.out.println("ito="); for(int i=0;i<ito.length;i++){ System.out.print(ito[i]+" "); } System.out.println(); solution.sortColors(ito);//執行程式 long end = System.currentTimeMillis(); System.out.println("rtn="); for(int i=0;i<ito.length;i++){ System.out.print(ito[i]+" "); } System.out.println(); System.out.println(); System.out.println("耗時:" + (end - begin) + "ms"); System.out.println("-------------------"); } }
解法1(成功,1ms,很快)
用的是題目中的一次掃描個數,二次重寫陣列的方法,沒想出來一次掃描排序
package pid075; import java.util.Arrays; import java.util.HashMap; import java.util.Map; public class Solution { public void sortColors(int[] nums) { int length=nums.length; if(length==0||length==1){ return; } int[] num=new int[3]; for(int i=0;i<length;i++){ int now=nums[i]; num[now]++; } for(int i=0;i<num[0];i++){ nums[i]=0; } for(int i=num[0];i<num[0]+num[1];i++){ nums[i]=1; } for(int i=num[0]+num[1];i<length;i++){ nums[i]=2; } return; } }
解法2(別人的)
如果只能掃一遍,很容易想到的就是左邊存放0和1,右邊存放2.兩邊往中間靠。
設定兩個index,left記錄第一個1的位置,left左邊為0,right記錄第一個非2的位置,right右邊為2.
然後使用i從頭到尾掃一遍,直到與right相遇。
i遇到0就換到左邊去,遇到2就換到右邊去,遇到1就跳過。
需要注意的是:由於left記錄第一個1的位置,因此A[left]與A[i]交換後,A[left]為0,A[i]為1,因此i++;
而right記錄第一個非2的位置,可能為0或1,因此A[right]與A[i]交換後,A[right]為2,A[i]為0或1,i不能前進,要後續判斷。
由此該陣列分為4段:[0,left)-->0; [left,i)-->1; [i,right]-->亂序; (right,n-1]-->2
0 0 0 1 1 1 2 1 0 2 1 2 2 2
^ ^ ^
left i right
public void sortColors(int[] nums) {
int j = 0, k = nums.length - 1;
for (int i = 0; i <= k; i++) {
// 遇到0和前面的交換
if (nums[i] == 0)
swap(nums, i, j++);
// 遇到2和後面的交換
else if (nums[i] == 2)
swap(nums, i--, k--);
}
}
private void swap(int[] nums, int i, int j) {
int t = nums[i];
nums[i] = nums[j];
nums[j] = t;
}