

今天面试就先到这里吧,回去等通知吧!
source link: https://www.cxyxiaowu.com/21814.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

一、题目描述
给定一个包含红色、白色和蓝色、共 n
个元素的数组 nums
,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。
我们使用整数 0
、 1
和 2
分别表示红色、白色和蓝色。
必须在不使用库的sort函数的情况下解决这个问题。
输入:nums = [2,0,2,1,1,0]
输出:[0,0,1,1,2,2]
输入:nums = [2,0,1]
输出:[0,1,2]
-
n == nums.length
-
1 <= n <= 300
-
nums[i]
为0
、1
或2
- 你可以不使用代码库中的排序函数来解决这道题吗?
- 你能想出一个仅使用常数空间的一趟扫描算法吗?
二、题目解析
这道题目有很多种解法。
但千万别做个“大聪明”,使用 sort 排序函数:
Arrays.sort(nums);

一行代码也通过了,但面试结果就是:今天面试就先到这里吧,回去等通知吧!

(图片来源于 LeetCode 75 号问题题解评论区)
因为题目有几个限制:
- 1、原地操作
- 2、不能使用代码库中的排序函数
- 3、常数级别的空间复杂度
- 4、扫描一遍
使用上面的 sort 函数就是和面试官较劲了。。。
这道题目是非常经典的「荷兰国旗问题」,由计算机科学家 Edsger W. Dijkstra 首先提出,掌握这道题目对于后续学习快速排序、三指针等知识点非常有帮助。
直接来说解法。
设置 3 个索引,left
指向数组的开始位置,right
指向数组的结束位置,index
指向数组的开始位置。

我们让 index
从头开始向后移动,在移动的过程中,它指向的元素会出现三种情况:
-
如果
index
位置上的元素值为 0,则说明是红色,要放在最前面去,此时最前面的那个元素被left
指着,所以让index
指向的元素和left
指向位置上的元素进行交换,交换完毕之后,说明 0 已经在它应该在的位置,即在整个数组的左区域,所以left
可以向后移动,index
也向后移动 -
如果若
index
位置上的元素值为 1,则说明是白色,就应该放在中间,不用管它,继续移动index
-
如果
index
位置上的元素值为 2,则说明是蓝色,要放在最后面,此时最后面的那个元素被right
指着,所以让index
指向的元素和right
指向位置上的元素进行交换,交换完毕之后,说明 2 已经在它改在的位置,即在整个数组的右区域,right
向前移动,但由于原先right
指向的元素可能为 0、1、2 这三种的任何一种,到了index
后,还需要继续观察一轮,所以index
先不移动
三、参考代码
// LeetCode 100 题精讲:https://mp.weixin.qq.com/s/yznC53g46phq3qF7V4-obA
// 作者:程序员吴师兄
// 颜色分类(LeetCode 75):https://leetcode.cn/problems/sort-colors/
class Solution {
public void sortColors(int[] nums) {
// left 指向数组的开始的位置,它指向的位置左侧都是 0
int left = 0;
// right 指向数组的结束的位置,它指向的位置右侧都是 2
int right = nums.length - 1;
// index 指向数组的开始位置
int index = 0;
// index 向后移动,当它越过 right 时跳出循环,不需要再判断了
// 因为此时说明 index 右侧的都已经是 2
while(index <= right){
// 获取当前的元素值
int cur = nums[index];
// 如果 index 位置上的元素值为 0
if(cur == 0){
// 说明是红色,要放在最前面去
// 最前面的那个元素被 left 指着,所以让 index 指向的元素和 left 指向位置上的元素进行交换
swap(nums,left,index);
// index 可以向后移动
index++;
// left 可以向后移动,它的左侧区域都是 0
left++;
// 如果 index 位置上的元素值为 1
}else if(cur == 1){
// 说明是白色,就应该放在中间,不用管它,继续移动 index
index++;
// 如果 index 位置上的元素值为 2
}else if(cur == 2){
// 说明是蓝色,要放在最后面
// 所以让 index 指向的元素和 right 指向位置上的元素进行交换
swap(nums,index,right);
// 由于原先 right 指向的元素可能为 0、1、2 这三种的任何一种
// 交换到了 index 后,还需要继续观察一轮,所以 index 先不移动
right--;
}
}
}
// 通过中间变量,交换两个元素的值
// nums[i] 的值变为了 nums[j] 的值
// nums[j] 的值变为了 nums[i] 的值
private void swap(int[] nums, int i ,int j){
// 使用临时变量 temp,保存 nums[i] 的值
int temp = nums[i];
// nums[i] 的值修改为 nums[j] 的值
nums[i] = nums[j];
// nums[i] 的值修改为 temp 的值
nums[j] = temp;
}
}
提交通过。

Recommend
-
14
这是why技术的第37篇原创文章 老规矩,先聊聊生活,上面这张图片是我周一拍的。 周一晚上下班后发现公司楼下推着三轮...
-
18
作者|Odin2020年2月,距离特朗普把华为列入实体清单后9个月。美国总统特朗普在电话上,知道英国首相约翰逊将会准许华为在英国兴建5G基建后,感到十分失望。即便约翰逊多番解释,但特朗普仍然当场气得怒摔电话。本来他们两人在2020年3月还有
-
33
推广 - @serco - 送的是亮星电动牙刷,可能有的朋友有看到过,有的没有* 拼多多新的专卖店开出来,需要破 0,所以就直接送了。* 一共**有 3 个链接,每个链接送 6 支**。每单限送一支,sku 任选,可
-
9
协同渠道之争,城市专营能否先到罗马? - IT业界_CIO时代网 - CIO时代—新技术、新商业、新管理协同渠道之争,城市专营能否先到罗马? 2021-10-12 17:31:57 来源: 摘要: 数字经济的浪潮正为企业服务市场...
-
4
🍅 简介:CSDN博客专家🏆、信息技术智库公号作者✌ 简历模板、PPT模板、学习资料、面试题库、技术互助【关注我,都给你】 🍅 欢迎点赞 👍 收藏 ⭐留言 📝
-
2
Redmi K50电竞版评测:一点“寒芒”先到 随后枪出如龙 【手机中国评测】当今时代,细分的游戏手机市场已经发展愈加成熟,不断丰富的产品、不...
-
2
众所周知HashMap是工作和面试中最常遇到的数据类型,但很多人对HashMap的知识止步于会用的程度,对它的底层实现原理一知半解,了解过很多HashMap的知识点,却都是散乱不成体系,今天一灯带你一块深入浅出的剖析HashMap底层实现原理。 看下面这些面试题,你能...
-
5
炎炎夏日,来份冰爽听单!限时领取,先到先得! 作者:
-
4
笃行致远 荣耀六大科技从领先到引领 成就世界荣耀 评论(11)...
-
22
SELECT COUNT(*) 会造成全表扫描?回去等通知吧 程序员大彬 2024-04-11 10:22:00 ...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK