题目描述:

给定一个包含红色、白色和蓝色,一共 n 个元素的数组,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。

此题中,我们使用整数 0、 1 和 分别表示红色、白色和蓝色。


示例 1:

输入:nums = [2,0,2,1,1,0]

输出:[0,0,1,1,2,2]


示例 2:

输入:nums = [2,0,1]

输出:[0,1,2]


示例 3:

输入:nums = [0]

输出:[0]


示例 4:

输入:nums = [1]

输出:[1]


提示:

1. n == nums.length

2. 1 <= n <= 300

3. nums[i] 为 0、1 或 2


进阶:

你可以不使用代码库中的排序函数来解决这道题吗?

你能想出一个仅使用常数空间的一趟扫描算法吗?


题目分析:

    这道题可以使用双指针解法使数组排序。首先定义左右指针分别指向数组头和尾。定义当前检查的标记位。遍历数组,如果当前元素为0,则应该把该元素放在数组最左边,所以我们将左指针指向的元素与当前元素交换,此时左指针指向的元素已经确定下来,右移左指针,继续检查下一个元素。如果当前元素为1,我们默认认为该元素位置是最终排序完该元素所在的位置,不移动左指针,如果后面元素存在0,再与此元素交换,继续检查下一个元素。如果当前元素为2,该元素应该放在数组的最右边,所以我们将当前元素和右指针指向的元素进行交换,交换完后右指针指向的位置元素已经确定,左移右指针,继续检查数组下一个元素。直到标记位越过右指针指向的位置,数组排完序。因为当前数组只有可能存在0,1,2这三个元素,所以我们才能用上述方法求解。


例如,假设输入nums = {2,0,2,1,1,0}。

首先让左右指针指向数组首尾,标志位指向数组首元素。首元素为2,应该放在数组最右边,交换首元素和右指针指向的元素。

LeetCode 75.颜色分类_双指针


交换后,右指针上的元素确定下来,左移右指针,继续检查当前标记位上的元素。

LeetCode 75.颜色分类_i++_02


当前标记位上的元素为0,交换当前元素和左指针指向的元素。此时左指针指向的元素确定下来,右移左指针,移动标记位继续检查下一个位置上的元素。

LeetCode 75.颜色分类_i++_03


当前标记位上的元素值还为0,交换当前元素和左指针指向的元素。此时左指针指向的元素确定下来,右移左指针,移动标记位继续检查下一个位置上的元素。

LeetCode 75.颜色分类_数组_04


当前标记位上的元素值为2,应该放在数组右边,交换当前元素和右指针指向的元素。

LeetCode 75.颜色分类_i++_05


右指针指向的元素值确定下来,左移右指针,检查当前标记位上的元素。元素值刚好为1,我们假设该元素位置为最终排完序的位置,继续检查下一个元素。

LeetCode 75.颜色分类_数组_06


该元素值也为1,继续检查下一个元素。

LeetCode 75.颜色分类_双指针_07


此时标记位已经越过右指针指向的位置,说明数组已经排完序。

LeetCode 75.颜色分类_数组_08


题解一(调用库函数):

执行用时: 0 ms

内存消耗: 36.8 MB

class Solution {
public void sortColors(int[] nums) {
Arrays.sort(nums);
}
}


题解二(双指针):

执行用时: 0 ms

内存消耗: 37.1 MB

class Solution {
public void sortColors(int[] nums) {
// 定义左右指针
int left = 0, right = nums.length - 1;
// 定义当前检查位置标记
int i = 0;
// 当标记位没有越过右指针位置时
while(i <= right) {
// 如果当前元素为0
if(nums[i] == 0) {
// 0元素应该放在数组最左边
// 所以交换当前元素和左指针指向的元素
swap(nums, i, left);
// 左指针右移一位
left++;
// 当前指针指向下一位
i++;
// 继续执行循环
continue;
}
// 如果当前元素为1
if(nums[i] == 1) {
// 当前指针指向下一位
i++;
// 继续执行循环
continue;
}
// 如果当前元素为2
if(nums[i] == 2) {
// 2元素应该放在数组最右边
// 所以交换当前元素和右指针指向的元素
swap(nums, i, right);
// 右指针左移一位,继续执行循环
right--;
}
}
}


// 交换数组两个元素的方法
public void swap(int[] nums, int i, int j) {
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
}


题目来源:力扣(LeetCode)