“双指针”
- 1. 原地移除元素
- 2. 删除排序数组的重复项(去重)
🍓今日如愿又吃了草莓
小边发现,这些对空间复杂度有要求 ——常常是 ,即要求原地怎怎样的题目,很适合用双指针的思想来解决。只不过,在顺序表中,所谓“指针”就是数组下标,但思想一致。
下面来两道典例——
注:要做好过程分析,时刻注意边界!
1. 原地移除元素
给你一个数组
nums
和一个值val
,你需要 原地 移除所有数值等于val
的元素,并返回移除后数组的新长度。不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地
元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
Leetcode链接:移除数字
示例:
输入:nums = [3,2,2,3], val = 3
输出:2, nums = [2,2]
解释:函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。你不需要考虑数组中
超出新长度后面的元素。例如,函数返回的新长度为 2 ,而 nums = [2,2,3,3] 或 nums
= [2,2,0,0],也会被视作正确答案。
🔑思路 —— “双指针”
src
找nums数组中不等于val的元素,把它放到dst
的位置上去,
再dst++
,src++
接着找下一个不等于val
的元素。(src
和dst
为数组下标)
过程分析——
🔑 完整代码
int removeElement(int* nums, int numsSize, int val){
int src = 0;
int dst = 0;
while(src<numsSize)
{
if(nums[src] != val)
{
nums[dst] = nums[src];
src++;
dst++;
}
else
{
src++;
}
}
return dst;
}
2. 删除排序数组的重复项(去重)
给你一个有序数组 nums ,请你 原地
不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。
示例:
输入:nums = [0,0,1,1,1,2,2,3,3,4]
输出:5, nums = [0,1,2,3,4]
解释:函数应该返回新的长度 5 , 并且原数组 nums 的前五个元素被修改为 0, 1, 2,
3, 4 。不需要考虑数组中超出新长度后面的元素。
那么,有了上一题的经验,很容易想到延续“双指针”的思路。
🔑三指针 —— 用两个指针确定重复区间,最后只留一个元素
快进到最后,找边界条件 ——
那j
越界了就停下,跳出循环后,还要处理一下,把最后一个值nums[i]也赋给nums[dst]
如果改一下数组,像下面这样的情况,j
越界很明显,上述做法也能一并处理。
int removeDuplicates(int* nums, int numsSize){
if(numsSize == 0)//处理空数组
return 0;
int dst = 0;
int i = 0;
int j = 1;
while(j < numsSize)
{
if(nums[i] == nums[j])
{
j++;
}
else
{
nums[dst] = nums[i];
dst++;
i = j;
j++;
}
}
nums[dst] = nums[i];
dst++;
return dst;
}