每临大事有静气,不信今时无古贤
1. 题目
给你一个数组 nums 和一个值 val,你需要 原地移除所有数值等于 val 的元素,并返回移除后数组的新长度。
这道题与 LeeCode 26 - daily03同属于数组 类型的题目。且在解法上也存在相同之处。
本题笔者也采用 双指针套路
2. 解法
注意 原地,往往意味着:拷贝覆盖
2.1 过程讲解
示例:nums = [3,2,2,3] value = 3
- low = 0 ; fast = 0; 结果:nums = [3,2,2,3] ,low = 0; fast = 1;
- low = 0 ; fast = 1 ; 结果:nums = [2,2,2,3] , low = 1; fast = 2;
- low = 1 ; fast = 2 ; 结果: nums = [2,2,2,3],low = 2 ; fast = 3;
- low = 2; fast = 3; 结果:nums = [2,2,2,3], low =2 ; fast = 4;
- 条件结束,返回low = 2;
详细步骤:请参考这里
2.2 不堪代码
public int removeElement(int[] nums, int val) {
// 处理边界条件
if(nums == null || nums.length == 0) return 0;
// 快慢指针
int low = 0;
// 需要特别强调的是,此处的快指针也是从0开始,WHY ?
int fast = 0;
while(fast < nums.length){
if(val == nums[fast]){
// 1.只更新快指针
fast ++;
}else{
// 原地:拷贝覆盖
nums[low] = nums[fast];
// 2. 快慢指针同时进步
low ++;
fast ++;
}
}
return low;
}
3. 技巧
遇见此类型题,高手直接都采用快慢指针。但是吾等菜鸟,还是需要稍思片刻…
一般而言,慢指针大部分都是从起始位置开始的(数组自然是从下标为0);
But快指针的设置还是有些技巧的。大部分情况下,既然是快指针,那自然是比慢指针要快一些,但也需要视情况而定。
3.1 快指针的设置要谨慎
要考虑情况,设定快指针。
以此题来展开论述:快慢指针是同时起步的。Why ?
因为数组的第一个值可能等于给定的值value. nums = [2], value = 2
3.2 快慢指针的步调问题
当使用快慢指针套路轻车熟路时,会发现这个套路是有规律可循的。
- 往往是在一种情况下,只更新快指针;
- 另一种情况下,快慢指针同时要求进步;
大家可以仔细揣摩一下
另外,做算法题笔纸随手把代码的过程给走一遍,会有很大帮助。