Leetcode 27. 移除元素

题源: Leetcode 27. 移除元素

思路

经典的双指针技术,这里称为快慢指针。其中,r(快指针)遍历数组,l(慢指针)跟踪新数组的填充位置。这种方法有效地在原数组上进行操作,避免了使用额外空间。

代码步骤
  1. 初始化l 指针初始化为 0,用于指示新数组的当前填充位置。

  2. 遍历数组

    • 使用 r 指针从 0 开始遍历数组 nums
    • 在每次迭代中,检查 nums[r] 是否等于 val
    • 如果 nums[r] 不等于 val,则将 nums[r] 的值赋给 nums[l],并将 l 指针向前移动一位。
  3. 返回结果:循环结束后,l 指针的位置表示了新数组的长度,因此直接返回 l

示例运行

假设 nums = [3, 2, 2, 3]val = 3

  • 初始状态:l = 0, r = 0
  • r = 0nums[r] = 3,与 val 相等,什么都不做,只增加 r
  • r = 1nums[r] = 2,与 val 不等,将 nums[r] 赋值给 nums[l]nums[0] = 2l 变为 1。
  • r = 2,同上,nums[1] = 2l 变为 2。
  • r = 3nums[r] = 3,与 val 相等,继续。
  • 结束遍历,返回 l = 2
    这种方法不仅高效,还操作简单,利用双指针技术避免了不必要的内存使用,并且能够直接在输入数组上进行修改,符合题目要求。这是解决类似问题的一种非常实用的技术,特别适合在需要避免使用额外空间的场景中使用。

复杂度

  • 时间复杂度:O(n),其中 n 是数组 nums 的长度。这是因为我们需要遍历整个数组一次,来检查每个元素是否需要被移除。

  • 空间复杂度:O(1),我们没有使用额外的数组或数据结构,所有操作都在原数组上完成。

Code

class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        int l = 0;
        for(int r = 0;r < nums.size();++ r){
            if(nums[r] != val) 
                nums[l ++ ] = nums[r]; 
        }
        return l;
    }
};

拓展

主要类型的双指针算法:

  • 对撞指针:

适用场景:常用于有序数组或链表,用来查找两个元素的特定关系(如和为固定值)。
工作方式:分别在数据结构的起始和结束位置放置两个指针,根据比较结果向中间移动。例如,在有序数组中查找两数之和为特定值的问题,如果当前两指针指向值的和小于目标值,则移动左指针增大和;如果大于目标值,则移动右指针减小和。
示例问题:两数之和、三数之和。

  • 快慢指针:

适用场景:主要用于处理循环或重复的问题,如检测链表中的循环。
工作方式:使用两个不同速度的指针(一个快指针和一个慢指针)。快指针每次移动两步,慢指针每次移动一步。如果存在循环,快慢指针最终会相遇。
示例问题:判断链表是否有环、寻找链表环的入口。

  • 滑动窗口(可视为一种双指针技术):

适用场景:用于数组或字符串中,寻找满足特定条件的连续子区间。
工作方式:维护一个窗口的左右边界,根据当前窗口内的数据情况决定扩大还是缩小窗口,直至找到所有满足条件的窗口。
示例问题:最小覆盖子串、长度最小的子数组。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值