1 题目
题目:颜色分类(Sort Colors)
描述:给定一个包含红,白,蓝且长度为 n 的数组,将数组元素进行分类使相同颜色的元素相邻,并按照红、白、蓝的顺序进行排序。
- 我们使用整数 0,1 和 2 分别代表红,白,蓝。
- 不能使用代码库中的排序函数来解决这个问题。
- 排序需要在原数组中进行。
- 你不可以使用计数排序(Counting Sort)来完成这道题目。
lintcode题号——148,难度——medium
该问题最早是由荷兰人Dijkstra提出的,所以该问题又叫荷兰旗问题。
样例1:
输入 : [1, 0, 1, 2]
输出 : [0, 1, 1, 2]
解释 : 原地排序。
2 解决方案
2.1 思路
可以把数组看成左、中、右三个区间,在一开始所有的数组元素都在中间的区间,使用一个指针(游标指针)指向数组头,遍历整个数组,如果遇到红色,则将其交换到左区间中,此处需要另一个指针(左指针)来指示左区间的范围;如果遇到蓝色,则将其交换到右区间中,同样需要另一个指针(右指针)来指示右区间的范围。遍历结束后,颜色即被分类完成。
2.2 时间复杂度
时间复杂度为O(n)。
2.3 空间复杂度
空间复杂度为O(1)。
3 源码
细节:
- 游标指针index遍历序列,找到0交换至左边,找到2交换至右边,找到1跳过,不断扩大左右分区,最后中间自然剩下的全部是1。
- 与右边交换的时候,需要注意游标指针在交换完成后并不右移,因为从右边交换回来的数还需要重新进入循环进行判断。
C++版本:
/**
* @param nums: A list of integer which is 0, 1 or 2
* @return: nothing
*/
void sortColors(vector<int> &nums) {
// write your code here
if (nums.size() < 2)
{
return;
}
int left = 0;
int right = nums.size() - 1;
int index = 0;
while (index <= right)
{
if (nums.at(index) == 0) // 命中0时,left和index都右移
{
swap(nums.at(left++), nums.at(index++));
continue;
}
if (nums.at(index) == 1) // 命中1时,index都右移,直接跳过该数
{
index++;
continue;
}
if (nums.at(index) == 2) // 命中2时,right都右移,index不动,交换回来的数还需要重新判断
{
swap(nums.at(right--), nums.at(index));
continue;
}
}
}