【LeetCode.27】 移除元素

港控/mmm° 2023-07-21 06:23 13阅读 0赞

题目描述

给你一个数组 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。
注意这五个元素可为任意顺序。
你不需要考虑数组中超出新长度后面的元素。

理解题意

  • 原地修改数组,指的是直接对数组参数 取下标来修改数组元素,而不是通过将数组参数引用指向一个新的数组。
  • 返回值为与val不等的元素个数。

解法——快慢指针

解法关键词

  • 双指针
  • 快慢指针
    在这里插入图片描述
  • 我们将算法结束后关心的前n个元素,称为压实数组。因为整个过程看起来就是在往左压实。
  • compactIndex代表即将加入压实数组的那个元素应该赋值的索引。所以初始时,compactIndex为0,因为初始时一个非val元素都没有得到确认。
  • cursor即为遍历指针。
  • 当遍历元素非val时,将其赋值给compactIndex位置,并compactIndex增加1.
  • 由于compactIndex刚好与压实数组的长度一样,所以函数返回compactIndex。
  • 图中最后一步,压实数组中两个元素颜色不同,是因为它们可能不相等,但都不是val。

    class Solution:

    1. def removeElement(self, nums: List[int], val: int) -> int:
    2. compactIndex = 0
    3. for cursor in range(len(nums)):
    4. if nums[cursor] != val:
    5. nums[compactIndex] = nums[cursor]
    6. compactIndex += 1
    7. return compactIndex

解法——双端指针

解法关键词

  • 双指针
  • 双端指针

题目中提到了元素的顺序可以修改,所以可以使用这种解法,时间复杂度一样。
在这里插入图片描述

  • 之间的解法是通过一个指针来遍历数组,现在则是通过两端的指针来遍历数组,通过待确认的元素纳入两个指针的范围内。左指针往右移动,右指针往左移动。
  • 通过left指针来判断压实数组的末尾,因为left总是指向 压实数组最大索引+1。(最大索引+1 就是长度)
  • 如果数组都是val,那么left不动,right一直移动;如果数组都非val,那么right不动,left一直移动。
  • 当left元素非val时,说明它不是想要的,则可以被覆盖,覆盖的值则是right元素,并right指针减1。因为下一次检查还是从left检查。
  • 当left元素为val时,说明它是想要的,确认了一个压实元素,则left指针移动。
  • 图中可见,五个元素只循环了五次。

    class Solution:

    1. def removeElement(self, nums, val):
    2. left = 0
    3. right = len(nums)-1
    4. while(left <= right):
    5. if nums[left] == val:
    6. nums[left] = nums[right]
    7. right -= 1
    8. else:
    9. left += 1
    10. return left
  • 因为right指向最大元素所在索引,所以区间是一个[left, right]的左闭右闭区间(每次循环中,待确认的元素,就在这个区间之中),所以最后一次循环肯定是left = right的情况。所以循环条件为left <= right
    在这里插入图片描述

    class Solution:

    1. def removeElement(self, nums, val):
    2. left = 0
    3. right = len(nums)
    4. while(left < right):
    5. if nums[left] == val:
    6. right -= 1
    7. nums[left] = nums[right]
    8. else:
    9. left += 1
    10. return left
  • 因为right指向最大元素所在索引+1,所以区间是一个[left, right)的左闭右开区间(每次循环中,待确认的元素,就在这个区间之中),所以最后一次循环肯定是left < right的情况。那么其实每次循环的条件都是left < right了,所以循环条件为left < right

发表评论

表情:
评论列表 (有 0 条评论,13人围观)

还没有评论,来说两句吧...

相关阅读

    相关 LeetCode27. 元素

    难度:`简单` 题目描述: > 给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。 > 不要使用额外

    相关 LeetCode27. 元素

    给定一个数组 nums 和一个值 val,你需要[原地][Link 1]移除所有数值等于 val 的元素,返回移除后数组的新长度。 不要使用额外的数组空间,你必须在[原地][

    相关 leetcode:27.元素

    题目描述: 给定一个数组 nums 和一个值 val,你需要原地移除所有数值等于 val 的元素,返回移除后数组的新长度。 不要使用额外的数组空间,你必须在原地修改输入