问题概述
给定一个数组和一个值,原地删除所有等于该值的元素。返回不等于该值的元素数量。
解法 1:双指针(推荐)
工作原理
使用两个指针:一个(k)跟踪下一个非 val 元素的位置,另一个(i)遍历数组。将非 val 元素复制到前面:
python
class Solution:
def removeElement(self, nums, val):
k = 0
for i in range(len(nums)):
if nums[i] != val:
nums[k] = nums[i]
k += 1
return k
复杂度分析
- 时间复杂度: O(n) - 单次遍历数组
- 空间复杂度: O(1) - 只使用常数额外空间
何时使用
- 推荐 - 标准方法,保持相对顺序
- 简单直观
- 适用于所有情况
解法 2:双指针交换
工作原理
从两端使用两个指针。当找到 val 时,将其与最后一个元素交换并减小数组大小。当 val 很少时,这避免了复制:
python
class Solution:
def removeElement(self, nums, val):
i = 0
n = len(nums)
while i < n:
if nums[i] == val:
nums[i] = nums[n - 1]
n -= 1
else:
i += 1
return n
复杂度分析
- 时间复杂度: O(n) - 每个元素最多访问两次
- 空间复杂度: O(1) - 只使用常数额外空间
何时使用
- 当 val 很少时(出现次数少)
- 顺序不重要(交换元素)
- 在某些情况下由于赋值更少而稍快
对比
| 方法 | 时间 | 空间 | 最佳适用 |
|---|---|---|---|
| 双指针 | O(n) | O(1) | 大多数情况,保持顺序 |
| 双指针交换 | O(n) | O(1) | 当 val 很少时,顺序不重要 |
总结
标准的双指针方法在大多数情况下是推荐的,因为它保持了元素的相对顺序。当要删除的值很少时,交换方法可能更快,但它会改变剩余元素的顺序。两种解决方案都具有 O(n) 时间和 O(1) 空间复杂度。