[LeetCode颜色分类] | 刷题打卡
此题是双指针类型的第10题。友情提示,此题仍然为双指针类型。
一直有刷题习惯,最近才看到掘金举办了刷题活动,特来参加!此题为第10题。不得不说掘金的主题就是漂亮呀!赞。
本文正在参与掘金团队号上线活动,点击 查看大厂春招职位
一、题目描述:
给定一个包含红,白,蓝且长度为 n 的数组,将数组元素进行分类使相同颜色的元素相邻,并按照红、白、蓝的顺序进行排序。
我们可以使用整数 0,1 和 2 分别代表红,白,蓝。
样例 1
输入 : [1, 0, 1, 2]
输出 : [0, 1, 1, 2]
解释 : 原地排序。
?>挑战
一个相当直接的解决方案是使用计数排序扫描2遍的算法。
首先,迭代数组计算 0,1,2 出现的次数,然后依次用 0,1,2 出现的次数去覆盖数组。
你否能想出一个仅使用常数级额外空间复杂度且只扫描遍历一遍数组的算法?
二、思路分析:
方法 | 描述 | 时间复杂度 | 空间复杂度 |
---|---|---|---|
双指针法 | 双指针的变种,三指针法 | ||
第一步 | 当nums[mid]==2 时,right 与mid 交换位置,right-- | ||
第二步 | 当nums[mid]==0 时,left 与mid 交换位置,left++,mid++ | ||
第三步 | 当nums[mid]==1 的,mid++ |
三、AC 代码:
/*
* @lc app=leetcode.cn id=75 lang=java
*
* [75] 颜色分类
*/
// @lc code=start
class Solution {
/**
* three tips:
* nums.length can be 2
* mid can equal right
* mid pcocess cases
*
* three pointer
* origin array:
* 1 0 2 1 0 1 0
* result array:
* 0 0 1 1 1 2 2 2
* | |
* L MID R
* @param nums
*/
public void sortColors(int[] nums) {
// back onditions
if (nums == null ) {
// fix bug ,length can be 2 or 1
return;
}
int left = 0;
int mid = 0;
int right = nums.length-1;
// fixt bug ,mid can equal right
while(mid <= right){
if(nums[mid] == 0){
// dose not care about right pointer
// keep pointer left to the left of 0
// 0 |
// L
swap(nums,mid,left);
left++;
mid++;
}else if(nums[mid] == 2){
// dose not care about mid pointer and right pointer
// keep pointer right with 2 to the right
// | 2
// R
swap(nums, mid, right);
right--;
// fix bug ,mid dose not process
}else{
// dose not care about left pointer and right pointer
mid++;
}
}
}
private void swap(int[] nums, int start, int end) {
int temp =nums[end];
nums[end] = nums[start];
nums[start] = temp;
}
}
// @lc code=end
四、总结:
此题的难点在于第三个指针:
- 第一次做题,很难想到再加一根指针
mid
, - 处理指针
mid
的思路不清晰,不清楚如何移动,mid
左移或右移的依据
题目收获:
- 此题为双指针的变形+相向双指针
- 引入mid指针之后,为后面划分算法、二分法可以做良好的铺垫
思路收获:
- 我们建立首尾双指针
left
和right
,分别指示0/1边界和1/2边界。left左边(不含left)全为0,right
右边(不含right
)全为2。 - 初始化
left
和mid
为0,right
为len(nums)-1
。 - 第三个指针mid从left起向right移动,边扫描边实时更新两个边界。
- 若
nums[mid]
为 0 :交换第mid
个和第left
个元素,并将left
指针和mid
指针都向右移。 - 若
nums[mid]
为 2 :交换第mid
个和第right
个元素,并将right
指针左移 - 若
nums[mid]
为 1 :将指针mid
右移。
补充一下,当mid
与left
交换后,mid
能够后移,因为此时nums[mid]
可能为0,后面还需要与left
交换。
- 若