LeetCode_Simple_27. Remove Element

2019.1.14

题目描述:

Given an array nums and a value val, remove all instances of that value in-place and return the new length.

Do not allocate extra space for another array, you must do this by modifying the input array in-place with O(1) extra memory.

The order of elements can be changed. It doesn't matter what you leave beyond the new length.

Example 1:

Given nums = [3,2,2,3], val = 3,

Your function should return length = 2, with the first two elements of nums being 2.

It doesn't matter what you leave beyond the returned length.

Example 2:

Given nums = [0,1,2,2,3,0,4,2], val = 2,

Your function should return length = 5, with the first five elements of nums
containing 0, 1, 3, 0, and 4.

Note that the order of those five elements can be arbitrary.

It doesn't matter what values are set beyond the returned length.

Clarification:

Confused why the returned value is an integer but your answer is an array?

Note that the input array is passed in by reference, which means modification to the input array will be known to the caller as well.

Internally you can think of this:

// nums is passed in by reference. (i.e., without making a copy)
int len = removeElement(nums, val);

// any modification to nums in your function would be known by the caller.
// using the length returned by your function, it prints the first len elements.
for (int i = 0; i < len; i++) {
    print(nums[i]);
}

这题是从数组中移除给定值的元素,最后返回剩余的元素个数(但是输入的是数组,这是因为输入数组是以“引用”方式传递的,这意味着在函数里修改输入数组对于调用者是可见的),前提是"就地",即空间复杂度为O(1).

解法一:

从数组左端开始扫描,另右端设置一个指针,同时记录数组中等于给定值的个数。

在左端下标小于等于右端下标的条件下进行如下循环:

1.如果左端的数字等于给定值,则从右端开始从右向左扫描,在右端下标大于左端的情况下,找出第一个不等于该给定值的数,并且下标要大于左端,将其赋值给左端,之后左移一位,

2.左端向右继续扫描

3.返回数组长度减去个数

C++代码:

class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        int len=nums.size();
        int j=len-1;
        int k=0;
        for(int i=0;i<=j;i++){
            if(nums[i]==val){
                k++;
                while(nums[j]==val&&j>i){
                    k++;
                    j--;
                    }
                nums[i]=nums[j--];
                }
            }
        return len-k;
    }
};

执行时间:4ms,by the way,第一次超过了99.8%,开心~

解法二:

双指针

既然问题要求我们就地删除给定值的所有元素,我们就必须用O(1) 的额外空间来处理它。如何解决?我们可以保留两个指针 i和 j,其中 i是慢指针,j 是快指针。

当 nums[j] 与给定的值相等时,递增 j 以跳过该元素。只要 nums[j]!=val,我们就复制 nums[j] 到 nums[i]并同时递增两个索引。重复这一过程,直到 j 到达数组的末尾,该数组的新长度为 i。

该解法与 删除排序数组中的重复项 的解法十分相似。

Java代码:

public int removeElement(int[] nums, int val) {
    int i = 0;
    for (int j = 0; j < nums.length; j++) {
        if (nums[j] != val) {
            nums[i] = nums[j];
            i++;
        }
    }
    return i;
}

**复杂度分析**

  • 时间复杂度:O(n), 假设数组总共有 n 个元素,i 和 j 至少遍历 2n 步。

  • 空间复杂度:O(1)。 

解法三:

当我们遇到nums[i]=val 时,我们可以将当前元素与最后一个元素进行交换,并释放最后一个元素。这实际上使数组的大小减少了 1。

请注意,被交换的最后一个元素可能是您想要移除的值。但是不要担心,在下一次迭代中,我们仍然会检查这个元素。

(与解法一相似,但不管最后的元素是不是等于给定值,而是直接赋值给nums[i],在下一次迭代中重新检查。)

Java代码:

public int removeElement(int[] nums, int val) {
    int i = 0;
    int n = nums.length;
    while (i < n) {
        if (nums[i] == val) {
            nums[i] = nums[n - 1];
            // reduce array size by one
            n--;
        } else {
            i++;
        }
    }
    return n;
}

复杂度分析

  • 时间复杂度:O(n),i 和 n 最多遍历 n 步。在这个方法中,赋值操作的次数等于要删除的元素的数量。因此,如果要移除的元素很少,效率会更高。

  • 空间复杂度:O(1)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值