删除数组中的重复项
给定一个排序数组,你需要在 原地 删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。
不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。
解题思路
使用双指针,重写原数组。
步骤
- 判断特殊情况
- 使用双指针
- 初始化两个指针,
let p = 0; let q = 1;,遍历数组 - 处理两种情况
- 如果
nums[q] !== nums[p], 则将nums[q]的值复制到nums[p + 1]的位置, 并将q++ - 如果
nums[q] === nums[p, 则不需要复制值,直接将p++
- 如果
- 初始化两个指针,
- 根据题目要求,返回数组长度
return p + 1。因为p是从0算起的。
代码
JavaScript
var removeDuplicates = function(nums){
if(nums === null || !nums.length){return 0}
let p = 0;
for(let q = 1; q < nums.length; q++){
if(nums[q] !== nums[p]){
p++;
nums[p] = nums[q]
}
}
return p+1
}
Java
public int removeDuplicates(int[] nums){
if(nums == null || nums.length == 0) return 0;
int p = 0;
int q = 1;
while(q<nums.lenght){
if(nums[p] !== nums[q]){
p++;
nums[p] = nums[q]
}
q++;
}
return p + 1;
}
复杂度
- 时间复杂度: O(n)
- 空间复杂度: O(1)
优化思路
考虑如下数组: nums = [1, 2, 3, 4, 5], 每次比较时 nums[p] 都不等于 nums[q],就会将 q 指向的元素原地复制一遍,这个操作没有必要,因此可以添加一个小判断, 当 q - p > 1 时,才进行复制。这里直接使用 q 和 p 比较是因为观察一个连续数字的数组,它们的索引相减值是1,或者使用 nums[q] - nums[p] > 1 也行,结果都一样。不过加了判断之后,需要注意 p 自增的位置,考虑一下,如果先自增后,判断 q - p > 1 的时候,p 的值就和 q 值相等,相减结果为0,也就是 p - q > 1 这个判断下的语句永远也不会执行。那这样就没有起到优化的效果。
写的过程中,一定要注意这些小细节。我也是第二遍重写的时候发现这个问题的。
我相信,跟我一样从头开始刷 LeetCode 的人可能会遇到各种各样的问题,可能在一些成熟的开发者面前这些都不算啥,但是记录下来有助于进步呀!
var removeDuplicates = function(nums){
let p = 0;
for(let q = 0; q < nums.length; q++){
if(nums[q] !== nums[p]){
// p++
// nums[p] = nums[q]
if(q - p > 1){
nums[p+1] = nums[q]
}
p++
}
}
return p + 1;
}