Leetcode 0075. 颜色分类 难度:mid
Leetcode 0075. 颜色分类 难度:mid
题目
给定一个包含红色、白色和蓝色,一共 n 个元素的数组,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。
此题中,我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。
注意:
不能使用代码库中的排序函数来解决这道题。
示例:
输入: [2,0,2,1,1,0]
输出: [0,0,1,1,2,2]
进阶:
一个直观的解决方案是使用计数排序的两趟扫描算法。
首先,迭代计算出0、1 和 2 元素的个数,然后按照0、1、2的排序,重写当前数组。
你能想出一个仅使用常数空间的一趟扫描算法吗?
代码实现:
思路1:
三指针的方法,思路非常简单,就是左右两个分别指向等待填充的0,2位置;
中间一个指针遍历 数组中元素。
遇到0, 交换到左侧; (交换回来的数,只能是1,因此可以跳过)
如果不跳过:0位置是值:0原地交换,会死循环。
遇到2,交换到右侧;(交换回来可能是0,1,2)后续可能还需要继续交换;
遇到1,跳过;
时间复杂度为:O(n)
class Solution {
public void sortColors(int[] nums) {
int left = 0 , right = nums.length -1;
int i = 0;
while(i <= right){
if(nums[i] == 0){
swap(nums, i, left);
left ++;
// 左侧交换回来的只能是1
i++;
} else if(nums[i] == 2){
swap(nums, i, right);
//右侧交换回来的,可能是0,1,2
right --;
} else {
i++;
}
}
}
public void swap(int[] nums, int i , int j){
if( i == j)
return;
int tmp = nums[i];
nums[i] = nums[j];
nums[j] = tmp;
}
}
思路2: 值是有取值范围的,我们可以直接使用count_sort();
继续排序需要额外的k个值空间。
时间复杂度:O(n); //第一趟:统计n 个元素; 第二趟:计数K个元素;第三趟: 从后往前,放置元素;
计数排序
class Solution {
public void sortColors(int[] nums) {
int[] count = new int[3];
for(int num :nums){
count[num] ++;
}
for(int i = 1; i < 3; i++ ){
count[i] += count[i-1];
}
int[] ans = new int[nums.length];
for(int i = nums.length -1; i >= 0; i--){
ans[count[nums[i]]-1] = nums[i];
count[nums[i]]--;
}
System.arraycopy(ans, 0, nums,0, nums.length);
}
}