劍指leetcode—顏色分類

題目描述:給定一個包含紅色、白色和藍色,一共 n 個元素的數組,原地對它們進行排序,使得相同顏色的元素相鄰,並按照紅色、白色、藍色順序排列。

此題中,我們使用整數 0、 1 和 2 分別表示紅色、白色和藍色。

注意:
不能使用代碼庫中的排序函數來解決這道題。

示例:

輸入: [2,0,2,1,1,0]
輸出: [0,0,1,1,2,2]

進階:

  • 一個直觀的解決方案是使用計數排序的兩趟掃描算法。
    首先,迭代計算出0、1 和 2 元素的個數,然後按照0、1、2的排序,重寫當前數組。
  • 你能想出一個僅使用常數空間的一趟掃描算法嗎?

方法一:

計數排序(給定範圍的計數排序)

class Solution {
    public void sortColors(int[] nums) {
        DistributionCountingSort(nums,0,2);
    }
    void DistributionCountingSort(int a[],int l,int u)
{
    int n=a.length;
    int [] D=new int [u-l+1];   
    int [] s=new int [n];
	int i,j;
	for(j=0;j<=u-l;j++)
	D[j]=0;     //初始化頻率數組 
	for(i=0;i<=n-1;i++)    //計算頻率值 
	D[a[i]-l]=D[a[i]-l]+1;   
	for(j=1;j<=u-l;j++)        //重用於分佈 
	D[j]=D[j-1]+D[j];
	for(i=n-1;i>=0;i--)
	{
		j=a[i]-l;
		s[D[j]-1]=a[i];
		D[j]=D[j]-1;
	}
      System.arraycopy(s, 0, a, 0, s.length);
}
}

時間效率很高,空間效率比較低。

方法二:

利用劃分的思想,實現三路快速排序

算法

  • 初始化0的最右邊界:p0 = 0。在整個算法執行過程中 nums[id < p0] = 0.

  • 初始化2的最左邊界 :p2 = n - 1。在整個算法執行過程中 nums[id > p2] = 2.

  • 初始化當前考慮的元素序號 :curr = 0.

  • While curr <= p2 :
    //這裏只可以是小於等於,因爲根據初始化2的最左邊界定義,如果只是小於數組中p2的數組元素並沒有被考慮

  • 若 nums[curr] = 0 :交換第 curr個 和 第p0個 元素,並將指針都向右移。

  • 若 nums[curr] = 2 :交換第 curr個和第 p2個元素,並將 p2指針左移 。

  • 若 nums[curr] = 1 :將指針curr右移。

class Solution {
    public void sortColors(int[] nums) {
        int n=nums.length;
        int p0=0;
        int p1=n-1;
        int cur=0;
        while(cur<=p1)
        {
            if(nums[cur]==0)
            {
                swap(nums,p0,cur);
                p0++;
                cur++;
            }
            else if(nums[cur]==2)
            {
                swap(nums,p1,cur);
                p1--;
            }
            else
            cur++;
        }
    }
    void swap(int [] nums,int a,int b)
    {
        int temp=nums[a];
        nums[a]=nums[b];
        nums[b]=temp;
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章