删除有序数组中的重复项
LeetCode 26:比较当前元素与最后一个已保留元素,原地完成有序数组去重。
给定一个非空、按非递减顺序排列的数组 nums(后一个数不小于前一个数),原地去重,使每个数只保留一次,返回唯一元素的数量 k。
保持元素的相对顺序,让数组的前 k 个位置保存去重结果,后面的内容可以忽略。要求使用 O(1) 额外空间。
示例 1:
- 输入:
nums = [1, 1, 2] - 返回:
2 - 修改后: 前两个元素为
[1, 2]。
示例 2:
- 输入:
nums = [0, 0, 1, 1, 1, 2, 2, 3, 3, 4] - 返回:
5 - 修改后: 前五个元素为
[0, 1, 2, 3, 4]。
1. 去重过程
数组有序,相同的数会连续出现。当前数与最后一个已保留的数相等,就跳过;不同,就追加到结果后面。 初始保留 nums[0],两个指针都从 0 开始:
fast:当前读取的下标,每轮前进一步。slow:最后一个已保留元素的下标。
下面用示例 2 演示。图中 index 是下标、value 是值,箭头标出每次操作前的指针位置。
第 1~2 轮:跳过相同的 0
| |
第一次将 nums[0] 与自身比较,第二次读到的仍是 0,都不写入。两轮后 fast = 2、slow = 0,已保留 [0]。
第 3 轮:追加新值 1
| |
1 与已保留的 0 不同,要放到它后面:先将 slow 从 0 移到 1,再执行 nums[1] = nums[2]。
这轮结束时 slow = 1、fast = 3,已保留 [0, 1]。
第 4~5 轮:跳过重复的 1
| |
fast 连续读到两个重复的 1,slow = 1 不动,fast 移到 5。
第 6~7 轮:追加 2,跳过重复的 2
| |
将 2 写入下标 2,后一个 2 跳过。两轮后 slow = 2、fast = 7。
第 8~9 轮:追加 3,跳过重复的 3
| |
将 3 写入下标 3,后一个 3 跳过。两轮后 slow = 3、fast = 9。
第 10 轮:追加最后的 4
| |
将 4 写入下标 4,随后 fast 移到 10,遍历结束。
结果占下标 0~4,共五个位置,保存 [0, 1, 2, 3, 4]。slow = 4 是最后一个已保留元素的下标,返回的长度是 slow + 1 = 5。
2. Python 实现
用 fast <= len(nums) - 1 遍历到最后一个元素,等价写法是 fast < len(nums)。
发现新值时,slow 在 fast 左侧,加 1 后也不会超过 fast,因此写入不会覆盖尚未读取的元素。
| |
| |
3. 复杂度
设 n 为输入数组的长度。
- 时间复杂度:
O(n),fast从左到右遍历一次,每个元素只检查一次。 - 额外空间复杂度:
O(1),原地覆盖元素,只维护两个下标变量。
评论
使用 GitHub 登录后参与讨论,评论将公开保存在 GitHub。
站长管理删除会同步到 GitHub,无法撤销。
阅读到这里时加载评论。