LeetCode.75. 颜色分类

此题就是“荷兰国旗问题”,题目如下:

给定一个包含红色、白色和蓝色、共 n 个元素的数组 nums ,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。
我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。
必须在不使用库的sort函数的情况下解决这个问题。

题目链接


思路一:
最先想到的肯定是排序算法,快排和计数排序。

快排代码

class Solution {
public:
    void sortColors(vector<int>& nums) {
        quick_sort(nums,0,nums.size()-1);
    }
    void quick_sort(vector<int>& nums,int l ,int r)
    {
        if(l >= r)return;
        int i = l-1,j = r+1,k = nums[l+r>>1];
        while(i < j)
        {
          do(i++);while(nums[i] < k);
          do(j--);while(nums[j] > k);
          if(i < j)swap(nums[i],nums[j]);
        }
        quick_sort(nums,l,j);
        quick_sort(nums,j+1,r);
    }
};

计数排序

class Solution {
public:
    void sortColors(vector<int>& nums) {
      int i = 0,j = 0,k = 0, n = nums.size();
      for(int m = 0;m < n;m++)
      {
          if(nums[m] == 0)
           i++;
          if(nums[m] == 1)
           j++;
          if(nums[m] == 2)
           k++;
      }
      for(int m = 0;m < n;m++)
      {
          if(m < i)
           nums[m] = 0;
           if( m >= i  && m < i+j)
           nums[m] = 1;
           if(m >= i+j && m < n)
           nums[m] = 2;
      }
    }
};

在这里插入图片描述两个都是4ms,只击败了40%


思路二:
利用双指针的思路:遍历第一遍,将 0 全部移动到最前面,与非0的交换位置;
遍历(其实不算遍历,从不是0的后一个开始,继续将 1 移动),最后的2就自然到最后面了。

class Solution {
public:
    void sortColors(vector<int>& nums) {
    int len = nums.size();
    int l = 0,r = 0;
    for(l = 0,r = 0;r < len;r++)
    {
        if(nums[r] == 0)
          swap(nums[l++],nums[r]);
    }
     for(r = l;r < len;r++)
     {
         if(nums[r] == 1)
           swap(nums[l++],nums[r]);
     }
    }
};

再优化一下,使得只要遍历一遍:
思路:我们用三个指针,第一个指针 i 用于遍历整个数组,另外两个指针分别用于交换1,0与 num[i] 的位置。
我们要注意:
指向 1 的指针不能慢于指向 0 的,否则会出现前面排好序的 0 被一个 1给 交 换位置了;

 class Solution {
public:
    void sortColors(vector<int>& nums) {
     int len = nums.size();
     int l = 0,r = 0;
     for(int i = 0;i < len ;i++)
     {
         if(nums[i] == 1)
         {
             swap(nums[i],nums[l++]);
         }
         else if(nums[i] == 0)
         {
             swap(nums[i],nums[r]);
             if(r < l)
             {
                 swap(nums[i] ,nums[l]);
             }
             r++;
             l++;
         }
     }
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值