题目:
Given an array with n objects colored red, white or blue, sort them in-place 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.
Example:
Input: [2,0,2,1,1,0]
Output: [0,0,1,1,2,2]
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 a one-pass algorithm using only constant space?
翻译:
给定一个包含n个红色、白色或蓝色对象的数组,对它们进行排序,使相同颜色的对象相邻,颜色顺序为红色、白色和蓝色。
这里,我们将使用整数0、1和2分别表示红色、白色和蓝色。
注意:对于这个问题,您不应该使用库的sort函数。
例子:
输入:[2 0 2 1 1 0]
输出:(0,0,1,1、2、2]
跟进:
一个相当直接的解决方案是使用计数排序的两步算法。
首先,迭代数组中0、1和2的个数,然后用total nu覆盖数组
思路:
这是一道经典的三颜色排序问题 ,可以采用双指针法解决。我们用0,1,2 对其进行排序,将0全部移到左边,2全部移到右边。那么1肯定就在中间了。
时间复杂度O(n) ,空间复杂度O(1)
代码实现:
方式一:
class Solution {
public void sortColors(int[] nums) {
int l=0;
int r=nums.length-1;
int index=0;
while(index<=r){
if(nums[index]==0){ //将当前指针==0的都移到左边
nums[index]=nums[l];
nums[l++]=0;
}
if(nums[index]==2){ //将当前指针==2的都移到右边
nums[index]=nums[r];
nums[r--]=2;
continue;
//因为从右边移过来的可能需要移到左边
//如果index++那么就会错过,所以continue
//上面的if不需要continue是因为其下面就有
//往右移的,因此不需要额外加continue
}
index++;
}
}
}
方式二:
class Solution {
public void sortColors(int[] nums) {
int l=0;
int r=nums.length-1;
int index=0;
while(index<=r){
if(nums[index]==0){
if(l==index){
index++;
l++;
}else{
nums[index]=nums[l];
nums[l++]=0;
}
}else if(nums[index]==1){
index++;
}else{
if(index==r)
return;
nums[index]=nums[r];
nums[r--]=2;
}
}
}
}
拓展:
给定n个有k种颜色的物体,把它们按照k种颜色排序。在整型数组中,用0,1,2…k-1分别表示k种颜色。不能使用排序函数。
思路:
这道题是三颜色排序的进化版,k颜色排序 ,总体还是采用双指针法。假设当前排序考虑的颜色范围是[c_min,c_max],则其初始值为c_min=0,c_max=k-1。 一轮排序之后,两种颜色c_min=0 , c_max=k-1处理完毕(两种颜色已经交换至两端) ,接下来需要考虑[c_min+1=1,c_max-1=k-2] 范围内的颜色排序,并重复步骤直至c_min>=c_max,退出该循环。
class Solution {
public void sortColors(int[] nums) {
int l=0;
int r=nums.length-1;
int index=0;
int c_min=0;
int c_max=k-1;
while(c_min<=c_max){ //这个等号可以不要。
while(index<=r){
if(nums[index]==c_min){
if(l==index){
index++;
l++;
}else{
nums[index]=nums[l];
nums[l++]=c_min;
}
}else if(nums[index]==c_max){
if(index==r)
break;
nums[index]=nums[r];
nums[r--]=c_max;
}else{
index++;
}
}
index=l;
c_min++;
c_max--;
}
}
}