LeetCode75:颜色分类与荷兰旗算法

给定一个包含红色、白色和蓝色,一共 n 个元素的数组,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。

此题中,我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。

示例:

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

 

先看这个题目,这个题目不仅仅是一个排序的问题,它的特点在于数组中的元素是固定的3个0,1,2,也就是说我们可以利用这个特性来优化一般性的排序

由于数组中只有0,1,2,因此最后排序完成后一定是0在前,2在后,1在中间。

如果我们使用三个指针left,right与cur。left一直指向0的后开区间,right指向2的前开区间,也就是说[0,left)间全为0,(right,nums.size()-1]间全为2。当cur为0时,交换left与cur的值,并将0区间的下限left右移;当cur=2时,交换right与cur的值,并将right左移。

 

现在唯一的问题在于循环这个过程中left,right,cur的加减问题。

现在假设cur已经领先于left:

首先对于left来说:

如果left为2,那么在之前cur遍历到这个2时已经将这个2交换到2区间了,也就是说left指向的值只可能是1(如果left指向的是0,则left应该在当前left的右边)。

其次对于right来说:

cur与right交换后,right原来的值可能是0,可能是1,也可能是2。

因此:

cur=0时,交换cur与left的值,并left++,且cur++;  cur++的目的是因为left指的值一定是1,因此交换后cur当前为1,cur=1既不用向前交换也不用向后交换,因此cur在交换后要自增一次。

cur=2时,交换cur与right的值,并right--,但此时cur不能自加了。  这里cur不能自加是因为,right原来指向的值可能是0,1,2。假如是1,当然可以自加,但如果是0或2,则自加后跳过了这个值,等价于没有对这个交换前的right的值进行排序,因此不能cur++。

class Solution {
public:
    void sortColors(vector<int>& nums) {
		if(nums.empty())
			return;
		int l=0;
		int r=nums.size()-1;
		int cur=0;
		while(cur<=r&&l<nums.size()&&r>=0)
		{
			if(nums[cur]==0)
			{
				swap(nums[l],nums[cur]);
				l++;
				cur++;
				continue;
			}
			if(nums[cur]==2)
			{
				swap(nums[r],nums[cur]);
				r--;
				continue;
			}
			cur++;
		}
    }
};

  

  

posted @ 2019-08-07 11:04  李湘沅  阅读(256)  评论(0编辑  收藏  举报