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?
注:
1、adjacent:相邻,邻近的,毗邻的
respectively:分别地、各自地
2、计数排序适用于元素个数非常有限的情况下
然后放回原有的数组
方法1:
class Solution {
public void sortColors(int[] nums) {
for(int i=0;i<nums.length-1;i++){
for(int j=i+1;j<nums.length;j++)
if(nums[i]>nums[j])
swap(nums,i,j);
}
}
private void swap(int[]nums,int l,int r){
int temp=nums[l];
nums[l]=nums[r];
nums[r]=temp;
}
}
方法二、
class Solution {
public void sortColors(int[] nums) {
int zeroCount=0;
int oneCount=0;
for(int i=0;i<nums.length;i++){
if(nums[i]==0){
zeroCount++;
}else if(nums[i]==1){
oneCount++;
}
}
for(int i=0;i<nums.length;i++){
if(i<zeroCount){
nums[i]=0;
}else if(i<zeroCount+oneCount){
nums[i]=1;
}else{
nums[i]=2;
}
}
}
}
方法三:
方法二对数组扫描了两边,那么有没有只扫描一遍就可以进行操作呢?
三路快排:每次选定一个标定点,但是由于有多个与这个标定点相同的值,所以将整个数组分为三份,分别为<V、==V和大于V,然后递归地向小于V和大于V的地方进行三路快排就可以了。由于只有三个元素,道理上只需要进行一次三路快排的操作就可以了。
//时间复杂度O(n)
//空间复杂度O(1)
//数组只遍历了一遍
public void sortColors(int[] nums) {
int zero=-1; //nums[0....zero]==0
int two=nums.length; //nums[two....n-1]==2
//arry[0,zero]==1 array[zeero+1,two-1]==1 arry[two,n-1]==2
for(int i=0;i<two; ){
if(nums[i]==0){
swap(nums,i++,++zero);
}else if(nums[i]==1){
i++;
}else if(nums[i]==2){
swap(nums,i,--two);
}else{ //保证所有元素都在0、1、2之间
return;
}
}
}
private void swap(int[]nums,int l,int r){
int temp=nums[l];
nums[l]=nums[r];
nums[r]=temp;
}