1. 程式人生 > >leetcode-75-顏色分類(sort colors)-java

leetcode-75-顏色分類(sort colors)-java

題目及測試

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