LeetCode 数组:75. 颜色分类(计数排序 荷兰国旗问题)

 

 

 

 是一道排序的题目

题目也提示了计数排序的方法。

当输入的元素是 n 个 0到 k 之间的整数时,时间复杂度是O(n+k),空间复杂度也是O(n+k)

 

题目后来的要求是常数空间复杂度O1空间复杂度,一趟扫描On,肯定是在计数排序上有所发展。

这时我们应该关注这道排序的特殊之处,因为没有一种通用的排序算法能做到这些复杂度要求。

这道题的特殊之处在于,只有三个元素(0,1,2),我们知道0放在前面,2放在后面,剩下的是1就行。

 

但这里说了O1空间复杂度,意味着我们要直接在原数组上面修改。我开始的想法是:设置一个0的最右位置,一个2的最左位置,然后遍历时碰到0就把最右位置改为0(相当于增加一个0),2就增加一个2,但这样会把原来的信息改没掉。

 

正确的方法是交换,p0指的是0区段的下一个,p2指的是2区段的上一个。cur指的是目前判断的数组。

如果cur是0,p1和cur做交换。0区间多了一个,自然加一。cur加一,是因为新的元素只会是1,而1不需要判断。也可能是第一个元素就是0,此时cur也需要前移。(这里注意,cur必须加一,如果不加一的话,如果碰到p1和cur都指向0的情况,cur会跑道p1的前面去,排序会完全乱掉

当cur为2时,p2和cur交换,p2减一,cur不用加一,因为我们不知道p2是什么值,需要进一步判断。

如果是1,不需要动。

 

这个问题被称为荷兰国旗问题

这个代码是自己三个月后写出来的,虽然出了两个bug(囧)

class Solution {
    public void sortColors(int[] nums) {
        if(nums.length==0)
        {return ;}
        //空数组特判
        int p1=-1,p2=0,p3=nums.length-1;
        //p1指向1区的开始,p2指向遍历,p3指向未排序区最后一个
        while(p3>=p2)//这里注意还有等于,当未排段只有一个元素时p2,p3重合
        {
            if(nums[p2]==0)
            {
                if(p1!=-1)
                {
                    nums[p1]=0;
                    nums[p2]=1;
                    p2++;
                    p1++;//这里一开始忘了维护p1指针的意义
                }
                else
                {
                    p2++;
                }
            }
            else if(nums[p2]==1)
            {
                 if(p1!=-1)
                 {
                     p2++;
                 }
                 else
                 {
                     p1=p2;
                     p2++;
                 }

            }
            else if(nums[p2]==2)
            {
                nums[p2]=nums[p3];
                nums[p3]=2;
                p3--;
            }
        }
    }
}

 

posted @ 2020-07-28 12:19  将来的事  阅读(321)  评论(0)    收藏  举报