LeetCode 26.删除有序数组中的重复项:前后指针解法

4 阅读2分钟

一、题目再解读

原题题干

1.给你一个 非严格递增排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。然后返回 nums 中唯一元素的个数。

2.考虑 nums 的唯一元素的数量为 k。去重后,返回唯一元素的数量 k

3.nums 的前 k 个元素应包含 排序后 的唯一数字。下标 k - 1 之后的剩余元素可以忽略。

核心规则(抓重点)

原地修改:不能新建数组,只能在原数组上改,空间复杂度O(1)​

返回值:返回移除后的数组长度k,原数组前k个元素为有效元素​

顺序有关:有效元素顺序不可以打乱,这是前后指针优化的关键​

无需处理k之后的元素,系统不会校验​ 示例演示

输入: nums = [1,1,2]
输出: 2, nums = [1,2,_]
解释: 函数应该返回新的长度 2 ,并且原数组 nums 的前两个元素被修改为 1, 2 。不需要考虑数组中超出新长度后面的元素。

解释:返回新长度2,数组前两位为有效元素,后续元素可忽略


二、新手踩坑实录(我的错误代码复盘)

一遍过 没有错 嘻嘻


三、最优解法:快慢双指针法(空间O(1),时间O(n))

解法思路

利用快慢双指针,头尾指针从数组开头向结尾遍历,核心逻辑:

数组是有序的 → 重复元素一定挨在一起

  1. 慢指针 slow:指向新数组最后一个有效位置

  2. 快指针 fast:遍历数组,找不重复的新元素

  3. 发现不一样 → 慢指针前进一步,把快指针的值覆盖过来

  4. 最后 slow + 1 就是新数组长度

var removeDuplicates = function(nums) { 
// 空数组直接返回0 
if (nums.length === 0) return 0; 
let slow = 0; 
// 慢指针:保存不重复元素 
for (let fast = 1; fast < nums.length; fast++) { 
// 快指针遍历 
// 发现不重复元素 
if (nums[fast] !== nums[slow]) { slow++; 
// 慢指针前进 nums[slow] = nums[fast]; 
// 覆盖赋值 
} } 
// 新数组长度 = slow + 1 
return slow + 1; };

四、复杂度分析

时间复杂度:O(n),数组仅遍历一次,前后指针移动总次数不超过2n

空间复杂度:O(1),仅用了两个指针变量,无额外数组空间开销,完全符合题目要求


五、结语

和上次的题目知识点很像,没什么难度,嘿嘿,继续加油