力扣本题传送门
我想的太简单了,最后console出来是真确答案,但就是执行不对,哎,想了也不能这么简单,我的简单错误代码如下
方法一
看了题解以后,发现用双指针,有循环一遍和循环2变得,就看明白了点儿,两次循环第一次把0放在前面第二次把1放在中间,代码如下
var sortColors = function (nums) {
let n = nums.length;
let index = 0;
// 从前往后遍历,只要发现有0的数字就交换,同时索引位置增加
for (let i = 0; i < n; i++) {
if (nums[i] == 0) {
// 这两句交换都ok
// [nums[index], nums[i]] = [nums[i], nums[index]];
[nums[i], nums[index]] = [nums[index], nums[i]];
index++;
}
}
console.log(nums, index)
// 经过上一轮之后索引位置前的数字都是0了,下一轮遍历就把后面所有1的数字都交换到中间
for (let i = index; i < n; i++) {
if (nums[i] == 1) {
[nums[i], nums[index]] = [nums[index], nums[i]];
index++;
}
}
};
题外话,双指针还是咩有掌握啊,我最开始想这个题目的时候,也是双指针,是一个往前一个往后,但是实现的跟我想象的比一样,我是想着0往前,2往后,1不变位置.我在集在方法一的基础上改造实现的错误代码如下
var sortColors = function (nums) {
let n = nums.length;
let index = 0;
// 从前往后遍历,只要发现有0的数字就交换,同时索引位置增加
for (let i = 0; i < n; i++) {
if (nums[i] == 0) {
// 这两句交换都ok
// [nums[index], nums[i]] = [nums[i], nums[index]];
[nums[i], nums[index]] = [nums[index], nums[i]];
index++;
}
}
console.log(nums)
// 经过上一轮之后索引位置前的数字都是0了,下一轮遍历就把后面所有1的数字都交换到中间
index = nums.length - 1;
for (let i = index; i > 0; i--) {
if (nums[i] == 2) {
[nums[i], nums[index]] = [nums[index], nums[i]];
index--;
}
}
};
其他人双指针实现正确的.
方法二
var sortColors = function (nums) {
let n = nums.length;
// p0确保前面位置的元素都是0
let p0 = 0,
// p2确保后面位置的元素都是2
p2 = n - 1;
// 为什么退出的时候是<=p2,因为p2指针后面的元素都是2了,但并不是p2指向的这个位置也是2,所以是<=
/* 举例来说 [2,0,1] ,经过一次交换变成了[1,0,2],这时p2指向0元素,如果就此就退出循环,那就还是无序的*/
for (let i = 0; i <= p2; i++) {
// 把前面的2全部都交换到后面去
while (i <= p2 && nums[i] == 2) {
[nums[i], nums[p2]] = [nums[p2], nums[i]];
p2--;
}
// p0记住前面有多少个0,并确保p0前面的元素都是0
if (nums[i] == 0) {
[nums[i], nums[p0]] = [nums[p0], nums[i]];
p0++;
}
}
};