题目描述
给定一个包含红色、白色和蓝色、共 n 个元素的数组 nums,原地 对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。 我们使用整数 0、1 和 2 分别表示红色、白色和蓝色。 必须在不使用库内置的 sort 函数的情况下解决这个问题。
进阶:你能想出一个仅使用常数空间的一趟扫描算法吗?
示例 1:
输入:nums = [2,0,2,1,1,0]
输出:[0,0,1,1,2,2]
示例 2:
输入:nums = [2,0,1]
输出:[0,1,2]
思路&js代码
1、插入排序
对 nums 执行插入排序,也就是对 i=0,1,2,…,n−1 依次执行如下过程:
- 现在前缀 nums[0] 到 nums[i−1] 是有序的,把 nums[i] 插入这个有序前缀,从而把前缀 nums[0] 到 nums[i] 变成有序的。
- 算法执行完后,nums 就是一个有序数组了。
var sortColors = function(nums) {
let p0 = 0, p1 = 0; // 0的数量是p0,0和1的数量是p1
for (let i = 0; i < nums.length; i++) {
const x = nums[i];
nums[i] = 2;
if (x <= 1) {
nums[p1++] = 1;
}
if (x === 0) {
nums[p0++] = 0;
}
}
};2、双指针
/**
* @param {number[]} nums
* @return {void} Do not return anything, modify nums in-place instead.
*/
var sortColors = function(nums) {
let zero = 0; // `zero` 指针,表示 0 的右边界
let two = nums.length - 1; // `two` 指针,表示 2 的左边界
let i = 0; // `i` 为当前遍历指针
while (i <= two) { // 遍历数组,直到 `i` 超过 `two`
if (nums[i] === 0) {
// 0 交换 `nums[i]` 和 `nums[zero]`,然后 `zero++` 和 `i++`
[nums[i], nums[zero]] = [nums[zero], nums[i]];
zero++;
i++;
} else if (nums[i] === 1) {
// 1 位置正确,直接 `i++`
i++;
} else {
// 2 交换 `nums[i]` 和 `nums[two]`,然后 `two--`(但 `i` 不变)
[nums[i], nums[two]] = [nums[two], nums[i]];
two--;
}
}
};