力扣数组
27.移除元素
27.移除元素
https://leetcode.cn/problems/remove-element
题目
给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。
不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并原地修改输入数组。
元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
示例 1:
输入: nums = [3,2,2,3], val = 3
输出: 2
解释: 函数应该返回新的长度 2,并且 nums 中的前两个元素均为 2。不需要考虑数组中超出新长度后面的元素。示例 2:
输入: nums = [0,1,2,2,3,0,4,2], val = 2
输出: 5
解释: 函数应该返回新的长度 5,并且 nums 中的前五个元素为 0, 1, 3, 0, 4。提示:
- 0 <= nums.length <= 100
- 0 <= nums[i] <= 50
- 0 <= val <= 100
思路
- 定义慢指针
slow(初始为 0),用于记录新数组的末尾位置(最终指向新数组最后一个元素的下一位); - 定义快指针
fast遍历整个原数组,筛选出不等于val的元素; - 遍历过程中:
- 若
nums[fast] != val,说明该元素是新数组需要保留的,将其赋值给nums[slow],然后slow后移一位; - 若
nums[fast] == val,跳过该元素(快指针继续前进,慢指针不动);
- 若
- 遍历结束后,
slow的值即为移除目标值后数组的新长度。
解法
nums = [0,1,2,2,3,0,4,2]
val = 2
def removeElement(nums, val):
slow = 0
for fast in range(len(nums)):
if nums[fast] != val:
nums[slow] = nums[fast]
slow += 1
return slow
new_length = removeElement(nums, val)
print(f"新长度: {new_length}, 数组前{new_length}个元素: {nums[:new_length]}")解释
| 代码片段 | 作用与原因 |
|---|---|
slow = 0 | 初始化慢指针,新数组的第一个有效元素从数组下标 0 开始存放 |
for fast in range(len(nums)) | 快指针遍历整个原数组,逐个检查每个元素是否需要保留 |
if nums[fast] != val | 筛选有效元素:仅保留不等于目标值 val 的元素 |
nums[slow] = nums[fast] | 将有效元素赋值到慢指针位置,实现“原地修改数组” |
slow += 1 | 慢指针后移,为下一个有效元素预留位置,同时统计有效元素数量 |
return slow | 慢指针的最终值等于有效元素的总数,即新数组的长度 |
进阶
如果要求“移除元素后保持剩余元素的相对顺序不变”,上述解法是否依然适用?
- 适用。因为快指针是按顺序遍历原数组,有效元素会按原顺序被赋值到慢指针位置,天然保证剩余元素的相对顺序不变;
- 若想进一步优化(减少赋值操作),可改用“首尾双指针”:左指针找等于
val的元素,右指针找不等于val的元素,交换两者位置,直到左右指针相遇。该方法可能改变元素顺序,但赋值次数更少。