LeetCode75 SortColors
题目描述
给定一个包含红色、白色和蓝色,一共 n 个元素的数组,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。
此题中,我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。
注意:
不能使用代码库中的排序函数来解决这道题。
示例:
输入: [2,0,2,1,1,0]
输出: [0,0,1,1,2,2]
解答
解法一:计数排序
第一趟遍历,计算出0,1,2的个数,然后按照0,1,2出现的个数重写当前数组。
public static void solve1(int[] nums){
int[] count= new int[3];
for(int i=0;i<nums.length;i++){
// if(nums[i]==0)
// count[0]++;
// else if(nums[i]==1)
// count[1]++;
// else if(nums[i]==2)
// count[2]++;
if (nums[i]<0||nums[i]>2)
return;
count[nums[i]]++;
}
for (int i=0;i<nums.length;i++){
if (i<count[0]){
nums[i]=0;
}else if (i>=count[0]&&i<count[1]+count[0]){
nums[i]=1;
}else if (i>=count[1]+count[0]&&i<count[2]+count[1]+count[0]){
nums[i]=2;
}
}
}
解法二:三指针法(三路快排)
利用三个指针,zero, i, two。分别表示的是:zero是当前最后一个0的索引位置,i 用来遍历数组,two是当前出现的第一个2的索引,即数组从[0,zero]存储的都是0,[zero+1, i -1] 存储的都是1,[i, two-1]为当前尚未遍历的元素,[two, 末尾] 存储的都是2.
一趟遍历,nums[i] 为0时,两种情况,一是i和zero相等时,直接zero+1,i+1,往下遍历,二是i和zero不相等时,与zero+1处的1做交换,zero++。但其实这两种情况都可以直接用两个语句来写:zero++; swap(numa,zero,i);
.
nums[i]为1时候,什么都不用做,i直接往后面走,i+1;
nums[i]为2时,需要与two-1位置处的数字做交换,于是[two-1,nums.length-1]处都为2,因为交换过来的数字不确定是几,所以需要再次遍历访问i位置上的数字。在本例的代码中,因为for循环上i已经固定递增1,所以i需要减一。
当i遍历到two的前一个时,结束循环。
public static void solve2(int[] nums){
int zero = -1; //[0,zero]中存储的是0
int two = nums.length; //[two, nums.length-1]中存储的是2
//第三个指针为i,用来遍历数组,从[zero+1,i-1]中存储的都是1
for (int i=0;i<two;i++){
if (nums[i]==0 ){ //遇到0的时候,与zero+1位置处的1做交换,此时[0,zero+1]存的都是0,[zero+2, i]都是1。
zero++;
swap(nums,zero,i);
}else if (nums[i]==2){ //遇到2的时候,与two-1位置处的数字做交换,于是[two-1,nums.length-1]处都为2,因为交换过来的数字不确定是几,所以需要再次遍历访问i位置上的数字。
two--;
swap(nums,two,i);
i--;
}
}
}
public static void swap(int[] source,int a, int b) {
int temp = source[a];
source[a]=source[b];
source[b]=temp;
}