携手创作,共同成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第14天,点击查看活动详情
颜色分类
给定一个包含红色、白色和蓝色、共
n
个元素的数组nums
,[原地]**对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。 我们使用整数0
、1
和2
分别表示红色、白色和蓝色。
必须在不使用库的sort函数的情况下解决这个问题。
分析
- 题目要求不使用库函数的情况原地排序,那就是基础的排序写法了,对于数组的原地排序,在写了这么多算法的基础上,暴力解决的方法先放一边,能比较容易的想到指针的解决方法
- 使用指针进行排序就是在符合排序条件的时候交换遍历的元素和指针指向的元素,把数组比作流水线的物品,指针比作安检员,几个指针就是几个安检员
单指针
- 在用1个指针的时候,就一个安检员,这个时候只能交换一种,比如是先区分0,1,然后区分1,2,这样就需要多一次遍历,显然速度是不够快的,随着网速越来越快,都是用空间换时间,就像检查物品多几个安检员同时开工自然是会快的,而只有3种物品,所以如果想遍历一遍就可以全部排好,2个安检员就够了
双指针
- 在两个指针的情况下,这两个指针有两种位置,一种是全都是从index=0出发,两个指针是快慢指针,一种是一个在头一个在尾,两个指针相向而行
- 在使用快慢指针的时候,最坏情况下每个指针都要遍历整个数组长度,如果是一个在头部一个在尾部相向而行,无论什么情况,头指针的遍历长度+尾指针的遍历长度=数组的长度,因此两个指针,头尾指针比快慢指针多了一些优化空间
- 在使用两个指针的时候,一个指针代表0和1的分界点,一个指针代表1和2的分界点,有0就往前排,有2往后排,中间自然就都是1
代码
var sortColors = function(nums) {
let l = 0;
let r = nums.length - 1;
let i = 0;
while (i <= r) {
const n = nums[i];
if (n === 0) {
[nums[i], nums[l]] = [nums[l], nums[i]];
l++;
i++;
} else if (n === 2) {
[nums[i], nums[r]] = [nums[r], nums[i]];
r--;
} else {
i++;
}
}
};
总结
- 排序是基础的算法之一,也是很有趣的算法,这个题目就是一种有趣的排序方式,双指针+头尾指针比较适合这类题目
- 今天也是有收获的一天