「这是我参与11月更文挑战的第18天,活动详情查看:2021最后一次更文挑战」。
题目
链接:leetcode-cn.com/problems/re…
给你一个有序数组 nums ,请你 原地 删除重复出现的元素,使每个元素 最多出现两次 ,返回删除后数组的新长度。
不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。
说明:
为什么返回数值是整数,但输出的答案是数组呢?
请注意,输入数组是以**「引用」**方式传递的,这意味着在函数里修改输入数组对于调用者是可见的。
你可以想象内部操作如下:
// nums 是以“引用”方式传递的。也就是说,不对实参做任何拷贝 int len = removeDuplicates(nums);
// 在函数里修改输入数组对于调用者是可见的。 // 根据你的函数返回的长度, 它会打印出数组中 该长度范围内 的所有元素。 for (int i = 0; i < len; i++) { print(nums[i]); }
示例 1:
**输入:**nums = [1,1,1,2,2,3]
**输出:**5, nums = [1,1,2,2,3]
**解释:**函数应返回新长度 length = 5, 并且原数组的前五个元素被修改为 1, 1, 2, 2, 3 。 不需要考虑数组中超出新长度后面的元素。
示例 2:
**输入:**nums = [0,0,1,1,1,1,2,3,3]
**输出:**7, nums = [0,0,1,1,2,3,3]
**解释:**函数应返回新长度 length = 7, 并且原数组的前五个元素被修改为 0, 0, 1, 1, 2, 3, 3 。 不需要考虑数组中超出新长度后面的元素。
提示:
1 <= nums.length <= 3 * 104-104 <= nums[i] <= 104nums已按升序排列
解题思路
思路1
题目要求: 每个元素 最多出现两次
循环一遍数组nums, 用m记录数字出现的次数, j记录替换位置, 当 当前和下一个不相等时, 替换nums[j] 为nums[i]
直到循环结束, 此时j为处理后的数组长度, 直接截断
i = 0, m = 1, j = 0, nums = [1,1,1,2,2,3]
i = 1, m = 2, j = 0, nums = [1,1,1,2,2,3]
i = 2, m = 3, j = 0, nums = [1,1,1,2,2,3]
i = 3, m = 1, j = 2, nums = [1,1,1,2,2,3]
i = 4, m = 2, j = 2, nums = [1,1,1,2,2,3]
i = 5, m = 1, j = 4, nums = [1,1,2,2,2,3]
i = 6, m = 1, j = 5, nums = [1,1,2,2,3,3]
//截断
i = 6, m = 1, j = 5, nums = [1,1,2,2,3]
/**
* @param {number[]} nums
* @return {number}
*/
var removeDuplicates = function(nums) {
let n = nums.length;
if (!n) return n
let j = 0
let i = 0
let m = 1
while (i < n) {
if (nums[i] !== nums[i + 1]) {
if (m > 1) nums[j++] = nums[i]
nums[j++] = nums[i]
m = 0
}
m++
i++
}
return nums.length = j
}
思路2
快慢指针
var removeDuplicates = function(nums) {
let n = nums.length;
if (n < 3) return n
let slow = 2
let fast = 2
while (fast < n) {
if (nums[slow - 2] !== nums[fast]){
nums[slow++] = nums[fast]
}
fast++
}
return nums.length = slow
};
思路3
设置快慢指针相同的起始位置,如果在移动的过程中一直都符合条件,那么快慢指针将一直相等地移动下去,直到最后输出数组的长度。
如果出现三次重复的,则只移动快指针。在纸上比划一下就可以理解。
26题删除有序数组中的重复项
仍可使用这道题的代码。将2全部改为1即可,道理一样
思路在注释中,第一行的判断不写也可以通过,因为用例里没有长度小于3的数组。
代码
/**
* @param {number[]} nums
* @return {number}
*/
var removeDuplicates = function(nums) {
// if (nums.length <= 2) return nums.length;
// s为slow指针 f为fast指针
let s = 2;//既代表索引(慢指针) 也代表最后记录的长度
// 以1开始 是因为 nums一定有值 经过前端筛选之后 最后输出长度最少是2
for (let f = 2; f < nums.length; f++) {//循环索引相当于快指针
if (nums[s - 2] !== nums[f]) {
nums[s] = nums[f];//原地修改
s++;//输出长度+1
}
// 相等的时候只移动快指针,即循环的索引
}
return s;
};