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

      

      

  • 相关阅读:
    coredump分析
    Sword LRU算法
    C++ STL迭代器失效问题
    Sword DB主从一致性的解决方法
    Sword CRC算法原理
    C语言 按位异或实现加法
    Linux 等待信号(sigsuspend)
    C语言 宏定义之可变参数
    Linux shell字符串操作
    C++ *和&
  • 原文地址:https://www.cnblogs.com/lxy-xf/p/11314054.html
Copyright © 2020-2023  润新知