每日一练——颜色分类(快慢指针排序)

目录

题目

代码

分析

案例模拟

重难点分析

自检复习 


题目

75. 颜色分类 - 力扣(LeetCode)

代码

//交换函数,交换指针a和指针b指向的整数
void swap(int *a, int *b){
    int t = *a;
    *a = *b;
    *b = t;
}

void sortColors(int* nums, int numsSize) {
    //双指针
    int p0 = 0, p1 = 0;
    //遍历数组
    for(int i = 0; i < numsSize; ++i){
        //把0丢给p0,此时如果p0<p1,也就是遇到过1,那p0指向的数必为1,需要把1丢给p1
        //p0左边都是0,p1左边排列好的0和1,p0在p1左边,所以p0所指必定为1
        if(0 == nums[i]){
            swap(&nums[i], &nums[p0]);
            if(p0 < p1){
                swap(&nums[i], &nums[p1]);
            }
            ++p0, ++p1;
        }
        //把1丢给p1,之后p1++
        else if(1 == nums[i]){
            swap(&nums[i], &nums[p1]);
            ++p1;
        }
        //指针总结
        //p0是慢指针只有在遇到0才++,所以p0左边都是0
        //p1是快指针,遇到0或1才++,所以p1左边都是0和1
    }
}

分析

案例模拟

i = 0


 i = 1

遇到了0,丢给p0,双指针++

 


i = 2


i = 3

遇到了1,丢给p1,p1++


i  = 4

遇到1,丢给p1,p1++ 


i = 5

遇到0,丢给p0,

此时p0 < p1,sums( i )的值丢给p1后,再双指针++ 

重难点分析

        这题最难理解的地方,在于遇到1,而且p0 < p1时,为什么要做这么麻烦的交换。也就是代码中的这部分:

        对应于上面案例分析中 i = 5 的时候。

        在这种解法中,p0是慢指针,只有在遇到0时才++,所以p0左边都是0;p1是快指针,遇到0或1时都会++,所以p1左边都是0和1,又因为p0已经把0都排好了,所以p1左边是按01排好的0和1。

        相对位置如下:

        所以,代码中p0 < p1 的含义在于,此时p0所指的一定是1,而1在与遇到的0交换后,还应该换到p1的脚下,这种情况下p0遇到的0的总数+1,p1遇到的0和1的总数也+1(有一对0和1内部交换),所以双指针++。

       


 而代码中的交换过程也显得比较复杂,还是靠图来辅助理解:

        可以看到,p0, p1和nums(i)他们相互交换了值,就像过节日三个好朋友互相交换礼物。

        再由上面的分析,我们可以知道,交换前p0的值为1,nums(i)的值为0,把数值填入能得到下表:

        可以看到,确实是实现了把0给p0,把1给p1的操作。

自检复习 

        如果你能完全分析出下面这个视频那就说明你真的有收获啦。

每日一练——颜色分类(快慢指针排序)

  • 18
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

伊H

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值