27 移除元素
独立完成
核心思路:快指针负责遍历整个列表,寻找所有不等于 val 的元素;慢指针指向下一个有效元素应该写入的位置。每找到一个有效元素,就把它写到慢指针位置,然后慢指针向后移动一位。最终慢指针的值就是有效元素的数量。
def removeElement(self, nums: List[int], val: int) -> int:
slow = 0
for fast in range(len(nums)):
if nums[fast] != val:
nums[slow] = nums[fast]
slow += 1
return slow
时间复杂度:O(n)
空间复杂度:O(1)
26 删除有序数组
独立完成
核心思路:利用快慢指针。慢指针始终指向当前最后一个不重复元素的位置,快指针从前往后遍历数组。当 nums[fast] != nums[slow] 时,说明找到了一个新的不重复元素,于是先将慢指针向后移动一位,再把这个新元素写入 nums[slow]。由于 slow 记录的是最后一个有效元素的索引,并且索引从 0 开始,所以最终不同元素的数量是 slow + 1,前提是数组不为空,因为空数组没有第一个元素,此时不能直接返回 slow + 1
def removeDuplicates(self, nums: List[int]) -> int:
if not nums:
return 0
slow = 0
for fast in range(len(nums)):
if nums[fast] != nums[slow]:
slow += 1
nums[slow] = nums[fast]
return 1+slow
时间复杂度:O(n)
空间复杂度:O(1)
75颜色分类
半独立完成
核心思路:因为数组中只可能有 0、1、2,可以先统计每个数字出现多少次,再重新写回数组
def sortColors(self, nums: List[int]) -> None:
count_0 = 0
count_1 = 0
count_2 = 0
for num in nums:
if num == 0:
count_0 += 1
elif num == 1:
count_1 += 1
else:
count_2 += 1
index = 0
for _ in range(count_0):
nums[index] = 0
index += 1
for _ in range(count_1):
nums[index] = 1
index += 1
for _ in range(count_2):
nums[index] = 2
index += 1
时间复杂度:O(n)
空间复杂度:O(1)
优化思路:使用三指针,将数组分成已排好 0 的区域、已排好 1 的区域、未处理区域和已排好 2 的区域。current 遍历未处理区域,遇到 0 就交换到左侧,遇到 1 就继续前进,遇到 2 就交换到右侧。处理 2 后不能移动 current,因为从右侧换过来的元素还没有检查。
def sortColors(self, nums: list[int]) -> None:
left = 0
current = 0
right = len(nums) - 1
while current <= right:
if nums[current] == 0:
nums[left], nums[current] = nums[current], nums[left]
left += 1
current += 1
elif nums[current] == 1:
current += 1
else:
nums[current], nums[right] = nums[right], nums[current]
right -= 1