正在找工作的猿六凯在投出无数份简历后,准备打开电脑看会电影放松下。突然接到面试官的电话,急忙跑到厕所接听。
![4cb431335f61b64be29475c02af15c6c.png](https://i-blog.csdnimg.cn/blog_migrate/e3ae6c983f130d106867e07e16a7356d.jpeg)
黑脸面试官
小猿同学,看你的简历说算法掌握的比较扎实,我来给你出道算法题。
![4cb431335f61b64be29475c02af15c6c.png](https://i-blog.csdnimg.cn/blog_migrate/e3ae6c983f130d106867e07e16a7356d.jpeg)
黑脸面试官
我们使用整数 0、1 和 2 分别表示红色、白色和蓝色。给定一个包含红色、白色和蓝色,一共 n 个元素的数组,对它们进行交换,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。
![4cb431335f61b64be29475c02af15c6c.png](https://i-blog.csdnimg.cn/blog_migrate/e3ae6c983f130d106867e07e16a7356d.jpeg)
黑脸面试官
比如输入: 2 0 2 1 1 0,输出: 0 0 1 1 2 2
猿六凯
这个很简单呀。左边部分都是0,中间部分都是1,右边部分都是2。结果是个升序数组。我们可以把数组按升序排序,这样就可以了。
![bb32b8e36a72907f1ec2b8ab2d4e63c6.png](https://i-blog.csdnimg.cn/blog_migrate/0b5462e8c93695063162bbf50c7b522b.jpeg)
![4cb431335f61b64be29475c02af15c6c.png](https://i-blog.csdnimg.cn/blog_migrate/e3ae6c983f130d106867e07e16a7356d.jpeg)
黑脸面试官
排序的时间复杂度是多少?
猿六凯
像快排,归并排序这样的算法,最优时间复杂度是O(nlogn)。
![bb32b8e36a72907f1ec2b8ab2d4e63c6.png](https://i-blog.csdnimg.cn/blog_migrate/0b5462e8c93695063162bbf50c7b522b.jpeg)
![4cb431335f61b64be29475c02af15c6c.png](https://i-blog.csdnimg.cn/blog_migrate/e3ae6c983f130d106867e07e16a7356d.jpeg)
黑脸面试官
有没有更优的解法?
猿六凯
嗯,我想想。
![bb32b8e36a72907f1ec2b8ab2d4e63c6.png](https://i-blog.csdnimg.cn/blog_migrate/0b5462e8c93695063162bbf50c7b522b.jpeg)
猿六凯
我想到了,我们遍历一遍数组,把红色,白色,蓝色的数量分被统计下,然后在原数组里依次放入相应个数的0,1,2就可以了。这样时间复杂度是O(n),空间复杂度是O(1)。
![bb32b8e36a72907f1ec2b8ab2d4e63c6.png](https://i-blog.csdnimg.cn/blog_migrate/0b5462e8c93695063162bbf50c7b522b.jpeg)
![4cb431335f61b64be29475c02af15c6c.png](https://i-blog.csdnimg.cn/blog_migrate/e3ae6c983f130d106867e07e16a7356d.jpeg)
黑脸面试官
不错,方法可行,还给出了时间复杂度和空间复杂度。你这解法扫描了数组几趟?
猿六凯
统计个数一趟,按顺序放入一趟,一共两趟。
![bb32b8e36a72907f1ec2b8ab2d4e63c6.png](https://i-blog.csdnimg.cn/blog_migrate/0b5462e8c93695063162bbf50c7b522b.jpeg)
![4cb431335f61b64be29475c02af15c6c.png](https://i-blog.csdnimg.cn/blog_migrate/e3ae6c983f130d106867e07e16a7356d.jpeg)
黑脸面试官
有没有扫描一趟的方法?
猿六凯
我想想。
![bb32b8e36a72907f1ec2b8ab2d4e63c6.png](https://i-blog.csdnimg.cn/blog_migrate/0b5462e8c93695063162bbf50c7b522b.jpeg)
猿六凯
嗯,,,,这个问题有点难,没想到。
![bb32b8e36a72907f1ec2b8ab2d4e63c6.png](https://i-blog.csdnimg.cn/blog_migrate/0b5462e8c93695063162bbf50c7b522b.jpeg)
![4cb431335f61b64be29475c02af15c6c.png](https://i-blog.csdnimg.cn/blog_migrate/e3ae6c983f130d106867e07e16a7356d.jpeg)
黑脸面试官
给你提示一下。
![4cb431335f61b64be29475c02af15c6c.png](https://i-blog.csdnimg.cn/blog_migrate/e3ae6c983f130d106867e07e16a7356d.jpeg)
黑脸面试官
我们的目的是把原来数组分成三部分:左边部分是0,中间部分是1,右边部分是2。我们可以看出,左边部分元素都小于中间部分元素,右边部分元素都大于中间部分元素。
猿六凯
左边部分小于中间部分,右边部分大于中间部分,咋听着和快排有点像。
![bb32b8e36a72907f1ec2b8ab2d4e63c6.png](https://i-blog.csdnimg.cn/blog_migrate/0b5462e8c93695063162bbf50c7b522b.jpeg)
![4cb431335f61b64be29475c02af15c6c.png](https://i-blog.csdnimg.cn/blog_migrate/e3ae6c983f130d106867e07e16a7356d.jpeg)
黑脸面试官
方向是对的,你再想想怎么做。
猿六凯
快排的时候,我们选一个基准,把小于基准的放在左边,大于基准的放在右边。对于这个题目,我们选1为基准。0小于1,放左边;2大于1放右边。这样一趟快排就可以了。
![bb32b8e36a72907f1ec2b8ab2d4e63c6.png](https://i-blog.csdnimg.cn/blog_migrate/0b5462e8c93695063162bbf50c7b522b.jpeg)
猿六凯
具体的,我们用i记录排好的0的最后一个位置,用j记录排好的2的第一个位置。用k记录中间未排的元素第一个位置,如下图。
![bb32b8e36a72907f1ec2b8ab2d4e63c6.png](https://i-blog.csdnimg.cn/blog_migrate/0b5462e8c93695063162bbf50c7b522b.jpeg)
![bfe34210c3bef0086299867110a82892.png](https://i-blog.csdnimg.cn/blog_migrate/773da7e7136e7725f02d5fcc437a18ca.png)
猿六凯
我们判断k所指向的元素与1的关系。
![bb32b8e36a72907f1ec2b8ab2d4e63c6.png](https://i-blog.csdnimg.cn/blog_migrate/0b5462e8c93695063162bbf50c7b522b.jpeg)
猿六凯
大于1就和未排序的最后一个位置交换,也就是j的前一个位置,如下图。
![bb32b8e36a72907f1ec2b8ab2d4e63c6.png](https://i-blog.csdnimg.cn/blog_migrate/0b5462e8c93695063162bbf50c7b522b.jpeg)
![8618c817fa2eddda4b850f9225d54318.png](https://i-blog.csdnimg.cn/blog_migrate/f3e6a6ad079145b606c98aabbeeb8f43.png)
猿六凯
小于1就和第一个位置1交换,也就是i的后一个位置,如下图。
![bb32b8e36a72907f1ec2b8ab2d4e63c6.png](https://i-blog.csdnimg.cn/blog_migrate/0b5462e8c93695063162bbf50c7b522b.jpeg)
![f770858a1c0454bd99fb1b77c81332bb.png](https://i-blog.csdnimg.cn/blog_migrate/05f57a020e38653dd4eedfef54152c28.png)
猿六凯
当k和j相遇就停止,如下图。
![bb32b8e36a72907f1ec2b8ab2d4e63c6.png](https://i-blog.csdnimg.cn/blog_migrate/0b5462e8c93695063162bbf50c7b522b.jpeg)
![9fcec3d4a47ecc08570984adef469837.png](https://i-blog.csdnimg.cn/blog_migrate/c16a9591a1b917caae59514a87e0aa85.png)
![4cb431335f61b64be29475c02af15c6c.png](https://i-blog.csdnimg.cn/blog_migrate/e3ae6c983f130d106867e07e16a7356d.jpeg)
黑脸面试官
嗯,总体思路没问题。有这么一个细节,你考虑了吗?
![4cb431335f61b64be29475c02af15c6c.png](https://i-blog.csdnimg.cn/blog_migrate/e3ae6c983f130d106867e07e16a7356d.jpeg)
黑脸面试官
比如k指向的元素大于1,j的前一个位置的元素是0。这样交换后,是不是要做其他处理?如下图。
![efbcc24a30bb3f85321ab1190ceff50e.png](https://i-blog.csdnimg.cn/blog_migrate/e1e2c269ec4dad4ac6f9a13561fe6d3d.png)
猿六凯
我想想。交换后,结果如下图。
![bb32b8e36a72907f1ec2b8ab2d4e63c6.png](https://i-blog.csdnimg.cn/blog_migrate/0b5462e8c93695063162bbf50c7b522b.jpeg)
![dda9c2068ea08239fac486710141454b.png](https://i-blog.csdnimg.cn/blog_migrate/836eedd539b73f82a468ebcf906025fd.png)
猿六凯
如果交换回来了0,我们这个不能直接让k+1,需要将0和i后面一个位置的数交换,如下图。
![bb32b8e36a72907f1ec2b8ab2d4e63c6.png](https://i-blog.csdnimg.cn/blog_migrate/0b5462e8c93695063162bbf50c7b522b.jpeg)
![50e82f2c40706f77ee5aa3e5f020824b.png](https://i-blog.csdnimg.cn/blog_migrate/1ff0af3c6e1316ed13e6441f87560e4a.png)
![4cb431335f61b64be29475c02af15c6c.png](https://i-blog.csdnimg.cn/blog_migrate/e3ae6c983f130d106867e07e16a7356d.jpeg)
黑脸面试官
嗯,不错,写下代码吧。
#include using namespace std;class Solution {public: void qiuckSort(vector<int>& a, int l, int r) { if (l >= r) return; //快排模板 int k = l; int i = l - 1, j = r + 1; while (k < j) { if (a[k] < 1) swap(a[k], a[++i]);//如果a[k]是0,和i后面一个位置元素交换,并且i+1。 if (a[k] > 1) swap(a[k--], a[--j]);//如果a[k]是2,和j前面一个位置元素交换。并且k-1,抵消后面的k++,来再次对该位置进行判断(可能交换回来个0)。 k++; } } void sortColors(vector<int>& nums) { qiuckSort(nums, 0, nums.size() - 1); }};int main() { int n;//数组元素个数 cin >> n; int num; vector<int> nums; while (n--) cin >> num, nums.push_back(num); Solution s; s.sortColors(nums); for (auto num : nums) { cout << num <<" "; }}
![4cb431335f61b64be29475c02af15c6c.png](https://i-blog.csdnimg.cn/blog_migrate/e3ae6c983f130d106867e07e16a7356d.jpeg)
黑脸面试官
分析下时间复杂度和空间复杂度。
猿六凯
一趟快排,只扫描了一趟数组,时间复杂度是O(n),空间上交换元素需要一个额外空间,空间复杂度是O(1)。
![bb32b8e36a72907f1ec2b8ab2d4e63c6.png](https://i-blog.csdnimg.cn/blog_migrate/0b5462e8c93695063162bbf50c7b522b.jpeg)
![4cb431335f61b64be29475c02af15c6c.png](https://i-blog.csdnimg.cn/blog_migrate/e3ae6c983f130d106867e07e16a7356d.jpeg)
黑脸面试官
恩,今天先到这,等下一轮面试吧。
猿六凯
恩恩,谢谢黑脸面试官。
![bb32b8e36a72907f1ec2b8ab2d4e63c6.png](https://i-blog.csdnimg.cn/blog_migrate/0b5462e8c93695063162bbf50c7b522b.jpeg)
![4cb431335f61b64be29475c02af15c6c.png](https://i-blog.csdnimg.cn/blog_migrate/e3ae6c983f130d106867e07e16a7356d.jpeg)
黑脸面试官
你说谁脸黑,你没下一次面试了。
对应leetcode题目:75. 颜色分类
此思路解题详情:
![706a8a34a1b9dd2f0c49f01495b93ab7.png](https://i-blog.csdnimg.cn/blog_migrate/72ae826ed85f31bcc091d75296619f13.png)
欢迎订阅,每周更新面试高频算法题。从思路,代码,时间复杂度等多方面进行分析。
![c80b3ab499046d4ecd780e32c73a84c4.png](https://i-blog.csdnimg.cn/blog_migrate/71ef2fe5b7579277e265030e827e281a.jpeg)