力扣27、移除元素(简单)

发布时间:2024年01月24日

1?题目描述

图1?题目描述

2?题目解读

????????对于给定的数组nums,要求移除其中值为val的元素,且不使用额外的数组空间,返回移除后数组的新长度。

????????数组nums中元素的顺序可以改变。

3?解法一:双指针

????????双指针法是解算法题常用且非常有效的一种方法。

3.1?解题思路

????????设置双指针left和right,指针right从左向右遍历数组元素,指针left更新数组nums中的元素。函数返回left。

3.2?设计代码

#include <iostream>
#include <vector>
using namespace std;
class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        int n = nums.size();
        int left = 0;
        for (int right = 0; right < n; right++) {
            if (nums[right] != val) {
                nums[left] = nums[right];
                left++;
            }
        }
        return left;
    }
};
int main() {
    int x[] = { 3,2,2,3 };
    int val = 3;
    vector<int> nums;
    for (int i = 0; i < 4; i++)
    {
        nums.push_back(x[i]);
    }
    Solution S;
    int ans = S.removeElement(nums, val);
    cout << ans << endl;
    return 0;
}

3.3?复杂度分析

  • 时间复杂度:O(n)
  • 空间复杂度:O(1)

3.4?提交结果

图2?双指针法代码执行结果

4?解法二:前移法

????????前移法是与双指针法非常相似的一种方法。不同的是,双指针法的left指针用于放置元素,前移法的变量k用于统计要删除的元素个数并将保留的元素前移k个位置。

4.1?解题思路

????????指针right遍历数组nums的元素,变量k统计要删除的元素的个数,同时将指针right扫描到的要保留的元素前移k个位置。

4.2?设计代码

#include <iostream>
#include <vector>
using namespace std;
class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        int n = nums.size();
        int k = 0; //k累计当前等于val的元素个数
        for (int right = 0; right < n; right++) {
            if (nums[right] == val) {
                k++;
            }
            else {
                nums[right - k] = nums[right];
            }
        }
        return n - k;
    }
};
int main() {
    int x[] = { 3,2,2,3 };
    int val = 3;
    vector<int> nums;
    for (int i = 0; i < 4; i++)
    {
        nums.push_back(x[i]);
    }
    Solution S;
    int ans = S.removeElement(nums, val);
    cout << ans << endl;
    return 0;
}

4.3?复杂度分析

  • 时间复杂度:O(n)。指针right遍历了一遍数组元素。
  • 空间复杂度:O(1)

4.4?提交结果

图3?前移法代码执行结果

5?解法三:双指针优化

????????对于这一题,可以将双指针法进行优化。

5.1?解题思路

????????本题数组nums中元素的顺序可以改变,所以可以使用while循环,通过双指针left和right,分别从左、从右扫描数组元素。指针left不仅遍历数组元素,也放置新元素。

????????当指针left和指针right重合时,结束循环。

5.2?设计代码

#include <iostream>
#include <vector>
using namespace std;
class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        int left = 0, right = nums.size();
        while (left < right) {
            if (nums[left] == val) {
                nums[left] = nums[right - 1];
                right--;
            }
            else {
                left++;
            }
        }
        return left;
    }
};
int main() {
    int x[] = { 3,2,2,3 };
    int val = 3;
    vector<int> nums;
    for (int i = 0; i < 4; i++)
    {
        nums.push_back(x[i]);
    }
    Solution S;
    int ans = S.removeElement(nums, val);
    cout << ans << endl;
    return 0;
}

5.3?复杂度分析

  • 时间复杂度:O(n)。指针left和指针right共同遍历了一遍数组元素。
  • 空间复杂度:O(1)。没有使用额外数组空间。

5.4?提交结果

图4?双指针优化代码执行结果

6 解题心得

  • 对于一道算法题,可以写出多种版本的代码,可以有多种解法。
  • 双指针法没有改变数组nums中元素的顺序,双指针优化法改变了数组nums中元素的顺序,但避免了一些不必要的数组元素的移动。
  • 前移法与双指针法有着非常相似的思想。
文章来源:https://blog.csdn.net/BraveTomato/article/details/135725962
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。