“双指针”

  • 1. 原地移除元素
  • 2. 删除排序数组的重复项(去重)


🍓今日如愿又吃了草莓

小边发现,这些对空间复杂度有要求 ——常常是 双指针问题@Leetcode -- 顺序表_数组,即要求原地怎怎样的题目,很适合用双指针的思想来解决。只不过,在顺序表中,所谓“指针”就是数组下标,但思想一致。

下面来两道典例——

注:要做好过程分析,时刻注意边界!

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],也会被视作正确答案。

🔑思路 —— “双指针”

srcnums数组中不等于val的元素,把它放到dst的位置上去,
dst++src++接着找下一个不等于val的元素。(srcdst为数组下标)

过程分析——

双指针问题@Leetcode -- 顺序表_算法_02

🔑 完整代码

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 。不需要考虑数组中超出新长度后面的元素。

那么,有了上一题的经验,很容易想到延续“双指针”的思路。

🔑三指针 —— 用两个指针确定重复区间,最后只留一个元素

双指针问题@Leetcode -- 顺序表_数组_03


快进到最后,找边界条件 ——

双指针问题@Leetcode -- 顺序表_算法_04

j越界了就停下,跳出循环后,还要处理一下,把最后一个值nums[i]也赋给nums[dst]

如果改一下数组,像下面这样的情况,j越界很明显,上述做法也能一并处理。

双指针问题@Leetcode -- 顺序表_leetcode_05

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;
}