algorithm-base/animation-simulation/数组篇/leetcode27移除元素.md
2021-07-29 02:33:38 +00:00

6.3 KiB
Raw Blame History

如果阅读时,发现错误,或者动画不可以显示的问题可以添加我微信好友 tan45du_one ,备注 github + 题目 + 问题 向我反馈

感谢支持,该仓库会一直维护,希望对各位有一丢丢帮助。

另外希望手机阅读的同学可以来我的 公众号:袁厨的算法小屋 两个平台同步,想要和题友一起刷题,互相监督的同学,可以在我的小屋点击刷题小队进入。

27. 移除元素

题目描述

给你一个数组 nums 和一个值 val你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。

不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。

元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。

示例 1:

给定 nums = [3,2,2,3], val = 3,

函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。

你不需要考虑数组中超出新长度后面的元素。

示例 2:

给定 nums = [0,1,2,2,3,0,4,2], val = 2,

函数应该返回新的长度 5, 并且 nums 中的前五个元素为 0, 1, 3, 0, 4。

注意这五个元素可为任意顺序。

你不需要考虑数组中超出新长度后面的元素。

暴力法

解析

该题目也算是简单题目,适合新手来做,然后大家也不要看不起暴力解法,我们可以先写出暴力解法,然后再思考其他方法,这对于我们的编码能力有很大的帮助。我们来解析一下这个题目的做题思路,他的含义就是让我们删除掉数组中的元素,然后将数组后面的元素跟上来。最后返回删除掉元素的数组长度即可。比如数组长度为 10里面有 2 个目标值,我们最后返回的长度为 8但是返回的 8 个元素,需要排在数组的最前面。那么暴力解法的话则就需要两个 for 循环,一个用来找到删除,另一个用来更新数组。

移除数组元素暴力法

总体思路就是这样的,后面的会不断往前覆盖。暴力解法也是不超时的,实现也不算太简单主要需要注意两个地方。

1需要先定义变量 len 获取数组长度,因为后面我们的返回的数组长度是改变的,所以不可以用 nums.length 作为上界

2我们每找到一个需要删除的值的时候需要 i--,防止出现多个需要删除的值在一起的情况,然后漏删。

题目代码

Java Code:

class Solution {
    public int removeElement(int[] nums, int val) {
        //获取数组长度
        int len = nums.length;
        if (len == 0) {
            return 0;
        }
        int i = 0;
        for (i = 0; i < len; ++i) {
            //发现符合条件的情况
            if (nums[i] == val) {
                //前移一位
                for (int j = i; j < len-1; ++j) {
                    nums[j] = nums[j+1];
                }
                i--;
                len--;
            }
        }
        return i;
    }
}

Python3 Code:

from typing import List
class Solution:
    def removeElement(self, nums: List[int], val: int)->int:
        # 获取数组长度
        leng = len(nums)
        if 0 == leng:
            return 0
        i = 0
        while i < leng:
            # 发现符合条件的情况
            if nums[i] == val:
                # 前移一位
                for j in range(i, leng - 1):
                    nums[j] = nums[j + 1]
                i -= 1
                leng -= 1
            i += 1
        return i

双指针

快慢指针的做法比较有趣,只需要一个 for 循环即可解决,时间复杂度为 O(n) ,总体思路就是有两个指针,前面一个后面一个,前面的用于搜索需要删除的值,当遇到需要删除的值时,前指针直接跳过,后面的指针不动,当遇到正常值时,两个指针都进行移动,并修改慢指针的值。最后只需输出慢指针的索引即可。

动图解析:

题目代码:

Java Code:

class Solution {
    public int removeElement(int[] nums, int val) {
          int len = nums.length;
          if (len == 0) {
              return 0;
          }
          int i = 0;
          for (int j = 0; j < len; ++j) {
                //如果等于目标值,则删除
                if (nums[j] == val) {
                    continue;
                }
                // 不等于目标值时则赋值给nums[i],i++
                nums[i++] = nums[j];
          }
          return i;
    }
}

Python3 Code:

class Solution:
    def removeElement(self, nums: List[int], val: int) -> int:
        i = 0
        for j in range(len(nums)):
            if nums[j] != val:
                nums[i] = nums[j]
                i += 1
        return i

C++ Code:

class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        int n = nums.size();
      	if(!n) return 0;
      	int i = 0;
      	for(int j = 0; j < n; ++j){
          if(nums[j] == val) continue;
          nums[i++] = nums[j];
        }
      	return i;
    }
};

Swift Code

class Solution {
    func removeElement(_ nums: inout [Int], _ val: Int) -> Int {
        if nums.count == 0 {
            return 0
        }
        var i = 0
        for j in 0..<nums.count {
            if nums[j] != val {
                nums[i] = nums[j]
                i += 1
            }

        }
        return i
    }
}

Go Code:

func removeElement(nums []int, val int) int {
    length := len(nums)
    if length == 0 {
        return 0
    }
    i := 0
    for j := 0; j < length; j++ {
        if nums[j] == val {
            continue
        }
        nums[i] = nums[j]
        i++
    }
    return i
}