LeetCode 27. Remove Element

本文详细解析了LeetCode中移除元素问题的两种解决方案,包括基础的快慢指针法和优化后的元素交换法,旨在帮助读者理解并掌握在原地修改数组并返回新长度的技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目

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]);
}

这道题完全就是昨天的Remove Duplicates from Sorted Array的翻版,上来的思路马上就是快慢指针,一想觉得没问题,一试还是觉得没问题,就快乐提交了,时间复杂度O(n),空间复杂度O(1),运行时间0ms,代码如下:

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;
    }
};

然后看了solutions发现有一个改进版本,思路来源于:如果遇到了[1, 2, 3, 4, 5],而我们要移除4,那么我们需要对1、2、3都进行一次冗余的赋值。为了消除这种冗余,由于题目说了元素的顺序可以改变,那么可以在每次遇到需要删除的元素时,把这个元素和数组最后一个元素进行交换,这样每次遇到需要删除的都能减少数组的size。代码运行时间4ms:

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

2022.10.22

这道题还是想了一下才写出来,可能刚开始被绕进去了。还是快慢指针,这次因为要remove某个特定值,所以这个值可能出现在第一个,所以fast和slow都从0开始。当fast == val的时候,不保留fast,直接让fast++;当fast != val的时候,当前的slow应该是当前的fast,并让slow和fast都++。也是,交完回来才发现可以简化写法,但逻辑没有那么直观。

class Solution {
    public int removeElement(int[] nums, int val) {
        int len = nums.length;
        if (len == 0) {
            return len;
        }
        
        int slow = 0;
        int fast = 0;
        
        while (fast < len) {
            // option 1
            if (nums[fast] != val) {
                nums[slow] = nums[fast];
                slow++;
                fast++;
            } else {
                fast++;
            }
            
            // option 2: improvement
            /* if (nums[fast] != val) {
                nums[slow] = nums[fast];
                slow++;
            }
            fast++; */
        }
        return slow;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值