75. 颜色分类
1.题目描述
给定一个包含红色、白色和蓝色、共 n
个元素的数组 nums
,原地 对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。
我们使用整数 0
、 1
和 2
分别表示红色、白色和蓝色。
必须在不使用库的sort
函数的情况下解决这个问题。
示例 1:
输入:nums = [2,0,2,1,1,0]
输出:[0,0,1,1,2,2]
示例 2:
输入:nums = [2,0,1]
输出:[0,1,2]
提示:
n == nums.length
1 <= n <= 300
nums[i] 为 0、1 或 2
进阶:
- 你可以不使用代码库中的排序函数来解决这道题吗?
- 你能想出一个仅使用常数空间的一趟扫描算法吗?
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/sort-colors著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
2.题解
2.1 计数法
2.1.1 思路
我的第一反应就是这个方法。
因为就只有三个数,然后顺序我们已经都知道了,所以只需要统计三个数的多少,之后一个个填进去就行了。就很简单粗暴,还不用指针换来换去。
2.1.2 Java代码
class Solution {
public void sortColors(int[] nums) {
int z=0,t=0,th=0;
for(int i=0;i<nums.length;i++){
if(nums[i] == 0){
z++;
}
else if(nums[i]==1){
t++;
}
else{
th++;
}
}
for(int i=0;i<nums.length;i++){
if(z>0){
nums[i] =0;
z--;
}
else if(t>0){
nums[i] =1;
t--;
}
else{
nums[i] =2;
th--;
}
}
}
}
2.2 单指针
2.2.1 思路
接下来的三种都是官方题解的方法,但是我总结一下,因为官方题解实在是太绕了。
其实单指针和上面的计数法差不多,不过单指针是用一个指针表示左边的已经排过序了,右边的还没有。
第一个循环是将所有的0
换到开头,用i
去找到0,然后ptr
是第一个不为0的位置,换完之后再将ptr++
。
第二个循环是将所有的1
,都换到0
的后面,也是用i
去找到1,然后和ptr交换。最后剩下的一部分就是2了。
2.2.2 Java代码
class Solution {
public void sortColors(int[] nums) {
int ptr = 0;
int n = nums.length;
for(int i=0;i<n;i++){
if(nums[i]==0){
int temp = nums[i];
nums[i] = nums[ptr];
nums[ptr] = temp;
ptr++;
}
}
for(int i=ptr;i<n;i++){
if(nums[i]==1){
int temp = nums[i];
nums[i] = nums[ptr];
nums[ptr] = temp;
ptr++;
}
}
}
}
2.3 双指针
2.3.1 思路
使用双指针就能够将两次遍历变成一次遍历,用p0
指针表示左边为0
,用p1
指针表示左边为1。
先将1换到p1
的位置,p1++;然后如果碰到了nums[i] == 0,就将这个值换到p0所在的位置。如果这个时候p0<p1,就说明p0被覆盖掉的值为1,就要再将nums[i]和p1换。最后都要将这两个值再加。
2.3.2 Java代码
class Solution {
public void sortColors(int[] nums) {
int n = nums.length;
int p0 =0,p1=0;
for(int i=0;i<n;i++){
if(nums[i] == 1){
int temp = nums[i];
nums[i] = nums[p1];
nums[p1] = temp;
p1++;
}
else if(nums[i]==0){
int temp = nums[i];
nums[i] = nums[p0];
nums[p0] = temp;
if (p0 < p1) {
temp = nums[i];
nums[i] = nums[p1];
nums[p1] = temp;
}
p0++;
p1++;
}
}
}
}
2.4 双指针2
2.4.1 思路
这是第二种双指针,上面的双指针是指向0和1,这个双指针是从两头指向0和2。
先通过while将2换到最后,然后再将0换到最前面。
2.4.2 Java代码
class Solution {
public void sortColors(int[] nums) {
int n = nums.length;
int p0=0,p2 = n-1;
for(int i=0;i<n;i++){
while(i<=p2&&nums[i]==2){
int temp = nums[i];
nums[i] = nums[p2];
nums[p2] = temp;
p2--;
}
if(nums[i] == 0){
int temp = nums[i];
nums[i] = nums[p0];
nums[p0] = temp;
p0++;
}
}
}
}