【LeetCode】27.移除元素

27.移除元素

知识点:数组;双指针

题目描述

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

示例1
输入:nums = [3,2,2,3], val = 3
输出:2, nums = [2,2]
解释:函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。你不需要考虑数组中超出新长度后面的元素。例如,函数返回的新长度为 2 ,而 nums = [2,2,3,3] 或 nums = [2,2,0,0],也会被视作正确答案。
示例2
输入:nums = [0,1,2,2,3,0,4,2], val = 2
输出:5, nums = [0,1,4,0,3]
解释:函数应该返回新的长度 5, 并且 nums 中的前五个元素为 0, 1, 3, 0, 4。注意这五个元素可为任意顺序。你不需要考虑数组中超出新长度后面的元素。

解法一:左双指针

这道题可以用和283题一模一样的方法去做,都是在移动一个指定元素,将不等于这个元素的都移动到最前面就可以了;

class Solution {
    public int removeElement(int[] nums, int val) {
        int index = 0;
        for(int i = 0; i < nums.length; i++){
            if(nums[i] != val){
                nums[index] = nums[i];
                index++;
            }
        }
        return index;
    }
}
  • python
class Solution:
    def removeElement(self, nums: List[int], val: int) -> int:
        index = 0
        for i in range(len(nums)):
            if nums[i] != val:
                nums[index] = nums[i]
                index += 1
        return index

时间复杂度:O(N);但是我们有两个指针从左到右,最差情况需要遍历两次数组;

解法二:首尾双指针

这道题和之前的283题中有一个区别:这道题目不用保持相对顺序;也就是把不等于val的值都移动到最前面就可以了,不用管它们之间的顺序。
遇到这种不用保持相对顺序的往往就不需要从前向后了,可以用首尾双指针,类似于快速排序;首指针逐渐增大,遇到等于val的停下,尾指针不断减小,遇到不等于val的停下,然后两者互换,然后接着走,直到两个指针碰面,这就相当于把数组遍历完了。

class Solution {
    public int removeElement(int[] nums, int val) {
        if(nums == null || nums.length == 0) return 0;  //边界条件
        int left = 0;
        int right = nums.length - 1;
        while(left < right){
            while(left < right && nums[left] != val){
                left++;
            }
            while(left < right && nums[right] == val){
                right--;
            }
            int temp = nums[left];
            nums[left] = nums[right];
            nums[right] = temp;
        }
        if(nums[left] == val) return left;     
        //首尾双指针的时候常在最后用到的判断方法,判断停下来的时候是落在哪了,如果落在不等于val值上,那要加1;如果等于val的时候,那就正好;
        else return left+1;
    }
}
  • python
class Solution:
    def removeElement(self, nums: List[int], val: int) -> int:
        left, right = 0, len(nums)
        while left < right:
            if nums[left] != val:
                left += 1
            else:
                nums[left] = nums[right-1]   #直接给左指针赋值
                right -= 1
        return left

时间复杂度:O(N);但是这种首尾指针碰头的方法,最多只需要遍历一次数组;

体会

快速排序的首尾双指针碰面的想法经常用到,这样可以有效的减少遍历数组的次数;
如果是要保持相对位置,那就只能从左到右,用左双指针;如果对相对顺序没有要求,那么就可以从两边开始,然后根据题目要求去交换首尾指针指向的元素。

posted @ 2021-07-31 15:55  Curryxin  阅读(173)  评论(0编辑  收藏  举报
Live2D