LeetCode日积月累:02.移除元素

LeetCode日积月累:02.移除元素

根据代码随想录的讲解顺序开始打卡学习,闲时更新。

代码随想录:https://www.programmercarl.com/0027.移除元素.html#_27-移除元素

LeetCode练习题目:https://leetcode-cn.com/problems/remove-element/

题目描述

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

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

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

示例

1
2
3
输入: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],也会被视作正确答案。
1
2
3
4
输入: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。注意这五个元素可为任意顺序。你不需要考虑数组中超出新长度后面的元素。

解决方案(own)

借本想法是建立前、后两个指针,前指针从前往后判断元素是否是移除,在发现需要移除的值后,后指针从后往前遍历寻找不等于val的元素,然后交换这两个指针对应的元素值。整个程序在前指针大于后指针时停止。算法总共只需遍历一次数组元素,时间复杂度为O(n)。

每次前后指针找到待移除元素时,数组总长度-1;该方法会改变删除后输出数组元素的相对位置。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Solution(object):
def removeElement(self, nums, val):
"""
:type nums: List[int]
:type val: int
:rtype: int
"""

## own solution
l = len(nums)
left_idx, right_idx = 0, l-1
temp = None
while left_idx <= right_idx:
if nums[left_idx] == val:
l -= 1
while nums[right_idx] == val and left_idx < right_idx :
right_idx -= 1
l -= 1
temp = nums[left_idx]
nums[left_idx] = nums[right_idx]
nums[right_idx] = temp
right_idx -= 1
left_idx += 1
return l

解决方案(others)

双指针法(快慢指针法): 通过一个快指针和慢指针在一个for循环下完成两个for循环的工作。

27.移除元素-双指针法

快慢指针均从前往后遍历, 当快指针遇到待删除元素时,慢指针暂停移动,快指针继续遍历,直到遇到非删除元素,然后将快指针对应的值赋值到慢指针所在位置,赋值后慢指针和快指针继续移动,最终到快指针遍历结束,此时慢指针的位置则为移除val后的数组长度。

因为是顺序遍历,最后输出的数组元素之间的相对位置与删除前一致。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Solution:
"""双指针法
时间复杂度:O(n)
空间复杂度:O(1)
"""

@classmethod
def removeElement(cls, nums: List[int], val: int) -> int:
fast = slow = 0

while fast < len(nums):

if nums[fast] != val:
nums[slow] = nums[fast]
slow += 1

# 当 fast 指针遇到要删除的元素时停止赋值
# slow 指针停止移动, fast 指针继续前进
fast += 1

return slow