【LeetCode-数组】移除元素

题目描述

给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。
不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。
元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
示例:

给定 nums = [0,1,2,2,3,0,4,2], val = 2,
函数应该返回新的长度 5, 并且 nums 中的前五个元素为 0, 1, 3, 0, 4。
注意这五个元素可为任意顺序。
你不需要考虑数组中超出新长度后面的元素。

题目链接:https://leetcode-cn.com/problems/remove-element/

思路1

遍历数组,当遇到要移除的元素时,将该元素后面的元素整体前移一位,模拟移除该元素,并将数组长度减一。遍历结束时,返回当前的数组长度即可。代码如下:

class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        int length = nums.size();   //当前数组的长度
        int i=0;
        while(i<length){
            if(nums[i]==val){
                for(int j=i; j<length-1; j++)
                    nums[j]=nums[j+1];
                length--;
            }
            else i++;
        }
        return length;
    }
};
  • 时间复杂度:O(n^2)
    时间复杂度最好为O(n)(该情况下不需要移除元素,遍历一遍即可),最差为O(n^2)(对应移除数组中所有元素的情况)。
  • 空间复杂度:O(1)
    申请额外内存不随输入规模的增大而增大。

思路2

使用两个指针i和j,其中i为慢指针,j为快指针。i,j都从数组头开始,j先出发,如果nums[j]!=val,则nums[i]=nums[j]并将i++,j遍历结束时,i就是此时的数组长度。代码如下:

class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        int i=0;
        for(int j=0; j<nums.size(); j++){
            if(nums[j]!=val){
                nums[i] = nums[j];
                i++;
            }
        }
        return i;
    }
};
  • 时间复杂度:O(n)
    j遍历一遍数组就行,所以为O(n).
  • 空间复杂度:O(1)

思路3

思路2其实很好了,时间复杂度和空间复杂度都在大多数情况下都是最优的。但如果要删除的元素数量较少,例如输入为[1,2,3,4,5],删除1,那么数组还是有很多不必要的移动操作。解决这一问题的办法类似于思路1:记录当前数组的长度length并遍历数组,如果当前元素nums[i]==val,则交换当前元素与最后一个元素,也就是swap(nums[i], nums[length-1]),并将length--。只有nums[i]!=val时,才判断下一个元素(i++),因为如果nums[i]==val,通过swap(nums[i], nums[length-1]),nums[length-1]也可能是要删除的元素(例如[2,1,2],删除2)。代码如下:

class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        int i=0;
        int length = nums.size();   //当前数组的长度
        while(i<length){
            if(nums[i]==val){
                swap(nums[i], nums[length-1]);
                length--;
            } else {
                i++;
            }
        }
        return length;
    }
};

-时间复杂度:O(n)
i最多移动n步,所以时间复杂度为O(n)。这种情况下赋值的次数等于要删除元素的数量。
-空间复杂度:O(1)

总结

当遇到删除数组中重复的元素时,可以使用一快一慢两个指针来解决。

原文地址:https://www.cnblogs.com/flix/p/12646287.html