搬砖小技巧|奇怪的知识又增加了

先上题目:

给定一个包含红色、白色和蓝色、共 n 个元素的数组 nums ,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。(我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。)

题目给出了例子,就是把形如{0,1,2,0,1}的数组排列成{0,0,1,1,2}。我一拍脑袋,这不简单,刷刷写完提交:

class Solution {
public:
    void sortColors(vector<int>& nums) {
        return sort(nums.begin(), nums.end());
    }
};

 提交果然成功过了,但我一想,事情应该没有这么简单,我仔细一看,之间下面写了一行字:

必须在不使用库的sort函数的情况下解决这个问题。

好吧好吧,重新开始。

题目要求原地对它们进行排序,因此不能建立新数组。通过交换来变出要的数组太难做到,那就需要知道这个数组中每一种元素的个数,然后对原来的数组进行赋值。 代码如下:

class Solution {
public:
    void sortColors(vector<int>& nums) {
        int array[3] = {0,0,0};
        for(int i=0;i<nums.size();i++)
        {
            array[nums[i]]++;
        }
        int index = 0;
        while(index<array[0])
        {
            nums[index] = 0;
            index++;
        }
        while(index<array[0]+array[1])
        {
            nums[index] = 1;
            index++;
        }
        while(index<array[0]+array[1]+array[2])
        {
            nums[index] = 2;
            index++;
        }
        
    }
};

array[0], array[1], array[2]分别存储nums这个数组中0,1,2的个数,然后再按照顺序,对nums进行赋值。

代码是正确的,也能在规定时间内通过,但还是觉得太繁琐,看来一圈评论区,大佬是这么做的:

class Solution {
public:
    void sortColors(vector<int>& nums) {
        int num0 = 0, num1 = 0, num2 = 0;
        for(int i = 0; i < nums.size(); i++) {
            if(nums[i] == 0) {
                nums[num2++] = 2;
                nums[num1++] = 1;
                nums[num0++] = 0;
            }else if(nums[i] == 1) {
                nums[num2++] = 2;
                nums[num1++] = 1;
            }else {
                nums[num2++] = 2;
            }
            cout << num0 << " " << num1 << " " << num2 << endl;
        }
    }
};

 由于我们最后得到的数组应该是由若干个0,若干个1,若干个2组成的数组,由于数组长度固定已知,其实我们只要知道从哪里开始0变成了1,又从哪里开始1变成了2。我之前的做法是先遍历一遍,知道0,1,2各自的数量,再遍历一遍根据得到的信息进行赋值,但是上述这段代码在一遍遍历中,完成了上述两件事情。

解释一下这段代码,以{0,2,1,0,1}为例:

我们用num0,num1,num2来记录最后一个0,1,2的位置,初始值均为0。

第一个数是0,那么比0大的1和2的位置都要往后顺移,由于这个位置是0,最后一个0也要往后移一个。[0]

第二个数是2,那么比2小的位置不变,最后一个2的位置要往后移一个。[0,2]

第三个数是1,那么比1大的2要往后瞬移一个,比1小的0不变,最后一个1的位置往后一个。[0,1,2]

第四个数是0,那么比0大的1和2的位置都要往后顺移,由于这个位置是0,最后一个0也要往后移一个。[0,0,1,2]

第五个数是1,那么比1大的2要往后瞬移一个,比1小的0不变,最后一个1的位置往后一个。[0,0,1,1,2]

num0num1num2nums
初始000[0,2,1,0,1]
111[0,2,1,0,1]
112[0,2,1,0,1]
123[0,1,2,0,1]
234[0,0,1,2,1]
245[0,0,1,1,2]

由此,用了三个指针,完成了原地变换,大佬不愧是大佬。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

鲸鲸爱柠檬

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

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

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

打赏作者

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

抵扣说明:

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

余额充值