题目描述
原题链接
给定一个包含红色、白色和蓝色、共 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]
提示:
- n == nums.length
- 1 <= n <= 300
- nums[i] 为 0、1 或 2
进阶:
Javascript
排序
这里用快排来展示
/*
* @lc app=leetcode.cn id=75 lang=javascript
*
* [75] 颜色分类
*/
// @lc code=start
function swap(arr, a, b) {
var temp = arr[a];
arr[a] = arr[b];
arr[b] = temp;
}
function quickSort(arr, begin, end) {
if (begin >= end - 1) return;
var left = begin;
var right = end;
do {
do left++; while (left < right && arr[left] < arr[begin]);
do right--; while (right > left && arr[right] > arr[begin]);
if (left < right) swap(arr, left, right)
} while (left < right);
var swapPoint = left == right ? right - 1 : right;
swap(arr, begin, swapPoint);
quickSort(arr, begin, swapPoint);
quickSort(arr, swapPoint + 1, end);
}
/**
* @param {number[]} nums
* @return {void} Do not return anything, modify nums in-place instead.
*/
var sortColors = function (nums) {
quickSort(nums, 0, nums.length);
};
// @lc code=end
单指针
思路:两次扫描,第一次将所有的0交换道最前面
第二次将所有的1交换到前面
之后2就都在最后面了
/*
* @lc app=leetcode.cn id=75 lang=javascript
*
* [75] 颜色分类
*/
// @lc code=start
/**
* @param {number[]} nums
* @return {void} Do not return anything, modify nums in-place instead.
*/
var sortColors = function (nums) {
const len = nums.length;
let ptr = 0;
for (let i = 0; i < len; i++) {
if (nums[i] === 0) {
[nums[i], nums[ptr]] = [nums[ptr], nums[i]]; // 交换
ptr++;
}
}
for (let i = ptr; i < len; i++) {
if (nums[i] === 1) {
[nums[i], nums[ptr]] = [nums[ptr], nums[i]];
ptr++;
}
}
};
// @lc code=end
双指针
在单指针的基础上改进,用第一个指针表示0,第二个指针表示1,这样就能一次扫描完成
/*
* @lc app=leetcode.cn id=75 lang=javascript
*
* [75] 颜色分类
*/
// @lc code=start
/**
* @param {number[]} nums
* @return {void} Do not return anything, modify nums in-place instead.
*/
var sortColors = function (nums) {
const len = nums.length;
let ptr1 = 0;
let ptr2 = 0;
for (let i = 0; i < len; i++) {
if (nums[i] === 0) {
[nums[i], nums[ptr1]] = [nums[ptr1], nums[i]];
if (ptr1 < ptr2) {
[nums[i], nums[ptr2]] = [nums[ptr2], nums[i]];
}
ptr1++;
ptr2++;
} else if (nums[i] === 1) {
[nums[i], nums[ptr2]] = [nums[ptr2], nums[i]];
ptr2++;
}
}
};
// @lc code=end
Java
其他解法
Java
Javascript
双指针2
上面的双指针方法还可以用另一种思路来解决
第一个指针表示0
第二个指针从后面开始,表示2
这样0 移动到最前面,2移动到最后面,这样1就肯定是在中间的了