问题描述
给定一个有n个元素的数组,数组中元素的取值只有0,1,2三种可能。为这个数组排序。
基本解法
1.计数排序
C++(Java代码和C++基本没区别,略了)
我们只需要遍历一遍数组,分别统计0,1,2的元素的个数,然后重新装填到数组中就实现了题目要求。
void sortColors(vector<int>& nums){
int count[3]={0};//只有三个元素的数组,分别用来存放0,1,2三个元素的个数。
//count[i]存放i这个元素的频率
for(int i=0;i<nums.size();i++){
assert(nums[i]>=0&&nums[i]<=2);
count[nums[i]]++;
}
//装填
int index=0;
for(int i=0;i<count[0];i++)
nums[index++]=0;
for(int i=0;i<count[1];i++)
nums[index++]=1;
for(int i=0;i<count[2];i++)
nums[index]=2;
}
上述排序算法时间复杂度为O(n),空间复杂度为O(k)。
2.三路快排
三路快排则是将数组分成了小于v,等于v,大于v的三个部分,当递归处理的时候,遇到等于v的元素直接不用管,只需要处理小于v,大于v的元素就好了。具体详细介绍不赘述。
void moveZero(vector<int>& nums){
int zero=-1;//nums[0...zero]==0,初始值为-1,因为没有默认第一个元素为0
int two=nums.size();//nums[two...n-1]==2
for(int i=0;i<two;){
if(nums[i]==1)
i++;
else if(nums[i]==2){
two--;
swap(nums[i],nums[two]);
}
else{
assert(nums[i]==0);
zero++;
swap(nums[i],nums[zero]);
}
}
}
上述算法时间复杂度为O(n),空间复杂度为O(1),整个算法只遍历了一遍。