# 题目

给你一个数组 nums 和一个值 val ,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。

不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组

元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。

27. 移除元素 - 力扣(LeetCode)

# 分析

如果暴力解法,两个 for 循环就可以解决,一个 for 遍历寻找目标元素,另一个 for 更新数组。

// 时间复杂度:O (n^2)
// 空间复杂度:O (1)
class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        int size = nums.size();
        for (int i = 0; i < size; i++) {
            if (nums[i] == val) { // 发现需要移除的元素,就将数组集体向前移动一位
                for (int j = i + 1; j < size; j++) {
                    nums[j - 1] = nums[j];
                }
                i--; // 因为下标 i 以后的数值都向前移动了一位,所以 i 也向前移动一位
                size--; // 此时数组的大小 - 1
            }
        }
        return size;
    }
};

在碰到有序数组去重的问题时,对于有序数组,可以使用双指针法移动快指针遍历数组,并使用慢指针记录不重复的元素。

双指针法 (快慢指针法):通过一快一慢两个指针在一个 for 循环下完成两个 for 循环的工作。

定义快慢指针

  • 快指针:寻找新数组的元素 ,新数组就是不含有目标元素的数组
  • 慢指针:指向更新 新数组下标的位置
// 时间复杂度:O (n)
// 空间复杂度:O (1)
class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        int slowIndex = 0;
        for (int fastIndex = 0; fastIndex < nums.size(); fastIndex++) {
            if (val != nums[fastIndex]) {
                nums[slowIndex++] = nums[fastIndex];
            }
        }
        return slowIndex;
    }
};

# 使用情况

双指针法是一种常用的算法技巧,用于解决一些数组和字符串相关的问题。它使用两个指针(通常称为快指针和慢指针)来遍历数组或字符串,根据特定的条件移动指针。

双指针法适用于以下情况:

  1. 排序数组:当数组已经排序(升序或降序)时,可以使用双指针法快速查找目标元素或确定满足某个条件的元素。
  2. 有序数组去重:对于有序数组,可以使用双指针法移动快指针遍历数组,并使用慢指针记录不重复的元素。
  3. 子数组或子序列问题:对于数组或字符串中连续的子数组或子序列问题(如最长连续递增子序列),可以使用双指针法维护一个滑动窗口,根据条件移动指针。
  4. 查找两个数组或字符串中的共同元素:若两个数组或字符串已排序,可以使用双指针法同时遍历两个数组或字符串,根据元素大小移动指针。

需要注意的是,双指针法的应用场景并不限于上述情况,具体要根据问题的特点和条件来判断是否适合使用双指针法。在一些情况下,还可以结合其他算法技巧来解决问题。

更新于