Medium
题目描述
给定一个包含红色、白色和蓝色,一共 n 个元素的数组,原地对它们进行排序,使得相同颜色的元素相邻,并按红色、白色、蓝色顺序排列。
此题中,我们使用整数 0、1 和 2 分别表示红色、白色和蓝色。
**注意:**不能使用代码库中的排序函数来解决这道题。
示例 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
**进阶:**你可以不使用代码库中的排序函数来解决这道题吗?你能想出一个仅使用常数空间的一趟扫描算法吗?
解题思路
这道题有两种经典解法:
方法一:计数排序(两次遍历)
- 第一次遍历统计0、1、2的个数
- 第二次遍历按统计结果重新填充数组
- 时间复杂度O(n),空间复杂度O(1)
方法二:荷兰国旗问题(一次遍历)【推荐】 这是经典的三路快排思想,使用三个指针:
left:指向下一个0应该放置的位置right:指向下一个2应该放置的位置curr:当前遍历位置
核心思路:
- 遇到0:与left位置交换,left和curr都右移
- 遇到1:curr直接右移(1已经在正确区域)
- 遇到2:与right位置交换,right左移,curr不动(因为交换来的元素还需要判断)
这种方法只需要一次遍历,是最优解法。当curr > right时结束,此时所有元素都已正确分类。
代码实现
class Solution {
public:
void sortColors(vector<int>& nums) {
int left = 0, right = nums.size() - 1, curr = 0;
while (curr <= right) {
if (nums[curr] == 0) {
swap(nums[left], nums[curr]);
left++;
curr++;
} else if (nums[curr] == 2) {
swap(nums[curr], nums[right]);
right--;
} else {
curr++;
}
}
}
};
class Solution:
def sortColors(self, nums: List[int]) -> None:
"""
Do not return anything, modify nums in-place instead.
"""
left, right, curr = 0, len(nums) - 1, 0
while curr <= right:
if nums[curr] == 0:
nums[left], nums[curr] = nums[curr], nums[left]
left += 1
curr += 1
elif nums[curr] == 2:
nums[curr], nums[right] = nums[right], nums[curr]
right -= 1
else:
curr += 1
public class Solution {
public void SortColors(int[] nums) {
int left = 0, right = nums.Length - 1, curr = 0;
while (curr <= right) {
if (nums[curr] == 0) {
int temp = nums[left];
nums[left] = nums[curr];
nums[curr] = temp;
left++;
curr++;
} else if (nums[curr] == 2) {
int temp = nums[curr];
nums[curr] = nums[right];
nums[right] = temp;
right--;
} else {
curr++;
}
}
}
}
/**
* @param {number[]} nums
* @return {void} Do not return anything, modify nums in-place instead.
*/
var sortColors = function(nums) {
let left = 0, right = nums.length - 1, curr = 0;
while (curr <= right) {
if (nums[curr]
复杂度分析
| 复杂度类型 | 荷兰国旗算法 | 计数排序 |
|---|---|---|
| 时间复杂度 | O(n) | O(n) |
| 空间复杂度 | O(1) | O(1) |
说明: 荷兰国旗算法只需要一次遍历,在实际应用中效率更高,是推荐解法。
相关题目
. Sort List (Medium)
. Wiggle Sort (Medium)
. Wiggle Sort II (Medium)