LeetCode75. 颜色分类

这一题的链接如下:
75. 颜色分类

有一个人数组只包含 0,1,2,写一个算法,将这个原数组直接排序

这一题的思路有很多,常见的思路是:

  • 排序
  • 双指针

排序

直接使用常见的排序算法就可以了,下面主要说第二种

双指针

可以想象这样一个场景,对一个数组进行遍历。
如果遇到的数字是 0,则将其放到左边,如果遇到的是 2,则将其移动到右边。

当思路有了以后,就可以考虑实现了,首先可以定义两个下标,分别记为 left、right。

每一次遇到 0 的时候,就将下标为 left 桶赋值为 0,然后 left++
每一次遇到 2 的时候,就将下标为 right 桶赋值为 2,然后 right–

所以就可以写出如下的代码:

for(int i = 0; i <= right; i++){
    if(nums[i] == 2 && i <= right){
         swap(nums,i,right);
         right--;
     }
     if(nums[i] == 0 ){
         swap(nums,left,i);
         left++;
     }
     
 }

这样的写法有一个问题,考虑如下数组:
[1,2,0],left = 0,right = 2;

第一次循环,此时判断 nums[0] = 1,因此什么都不用做
第二次循环,此时判断 nums[1] = 2, 所以发生交换,因为right = 2,所以交换后:[1,0,2]

但是这个答案明显是错误的,造成这个问题产生的原因是 right 被错误的换掉了,可以这样理解,i 在每一次的循环都是会 ++ 的,而一旦 right 是几个连续的 2, 就会有问题
[1,2,X,X,X,2,2,2]
假设此时 i = 1,right = 6,因为 nums[1] = 2, 所以此时的数组就是 还是不变,但是因为 i 增加了,所以此时 下标为 1 的那个桶就是错误的数据了。

修复

修复的方案也很简单,直接循环到 right 不等于 2 的地方即可

int left = 0;
int right = nums.length - 1;
for(int i = 0; i <= right; i++){
    while(nums[i] == 2 && i <= right){
        swap(nums,i,right);
        right--;
    }
    if(nums[i] == 0 ){
        swap(nums,left,i);
        left++;
    }
}

思考

为什么左边就不需要进行循环呢?
出现这个问题的原因在于 i 是增加的,而且在遍历的过程中,已经将所有的 0 都处理了
[0,0,0,0,0]
[0,1,0,0,0]
[1,0,0,0,0,]

以上都不会出现问题

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值