Given an array with n objects colored red, white or blue, sort them so that objects of the same color are adjacent, with the colors in the order red, white and blue.
Here, we will use the integers 0, 1, and 2 to represent the color red, white, and blue respectively.
Note:
You are not suppose to use the library's sort function for this problem.
Follow up:
A rather straight forward solution is a two-pass algorithm using counting sort.
First, iterate the array counting number of 0's, 1's, and 2's, then overwrite array with total number of 0's, then 1's and followed by 2's.
Could you come up with an one-pass algorithm using only constant space?
问题其实就是给只包含0,1,2的整数数组排序。
看到题目马上就能想到一种直观的解决方法。思路一:用三个计数器分别记下0,1,2出现的次数,然后用循环把对应个数的数字放进原数组。Follow up说了这种straightforward的solution需要两趟遍历,有没有更简单的解决办法?
一趟遍历解决,我首先想到了前两天复习过的快排算法的partition函数。快排种一般取nums[0]为pivot,然后partition完成将大于pivot的数字放左边,大于pivot的数放右边。这个问题中,想找到pivot=1并不是一件容易的事,因为必须保证找到的pivot左边全部都是0(否则再次调整就又涉及到第二次遍历了)。
我用快排的思路想了一个小时还没有解决这个问题,最后看了下别人的解答。看代码:
void sortColors(vector<int>& nums) {
int zero = 0, two = (int)nums.size() - 1;
for (int i = 0; i <= two; i++) {
while (nums[i] == 2 && i < two) {
swap(nums[i], nums[two]);
two--;
}
while (nums[i] == 0 && i > zero) {
// i > zero condition ensures that when nums[] = {0}, it doesn't swap(nums[0], nums[0]) forever.
swap(nums[i], nums[zero]);
zero++;
}
}
}
zero和two分别维护从两侧向中间生长的全0和全2子串,它们指向的地方是下一个0或2要被插入的地方,新插入的数字来自于nums[zero...two]这个逐渐缩短的区间。需要注意的是第二个while循环中要设置条件 i > zero,用来跳过第一次运行时的corner case。两个判断是while而不是if的原因是可能nums[i]在经历第一次swap之后换来的还是原来的那个数字,即有可能:
nums[i] = nums[two] = 0 或 2
今天清明节,凌晨错过了巴萨罗马的欧冠比赛,上午睡到十点多起床。昨晚开始看CMU的Intro. to Computer Systems 15-213的公开课视频了,后续还有CS61B和OS要看,争取在去SD之前看完。昨天刷了4道还是5道题,终于LC刷题数过100了。今天白天刷了两道easy题和这个medium,虽然medium这个做的不理想。加油吧,要时刻认识到自己还是个菜鸡。