题目描述:
给你一个 升序排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持一致 。然后返回 nums 中唯一元素的个数。
更改数组 nums ,使 nums 的前 k 个元素包含唯一元素,并按照它们最初在 nums 中出现的顺序排列。nums 的其余元素与 nums 的大小不重要。返回 k
输入:nums = [1,1,2]
输出:2, nums = [1,2,_]
解释:函数应该返回新的长度 2 ,并且原数组 nums 的前两个元素被修改为 1, 2 。不需要考虑数组中超出新长度后面的元素。
解题思路:
- 用对象来记录所有的数字,如果这个数字对应的值为1,说明是重复数字
- 双指针
- 数组去重第一想法就是用集合来去重,但是形参进来,改变不了传递的数组,但是真的很方便。随便写一下,并不能跑通,硬改也能成功
function removeDuplicates(nums) {
nums = [...new Set(nums)];
return nums.length;
}
解法一:对象键(效率极低)
function removeDuplicates(nums) {
// 创建一个对象
let obj = {};
for (let i = 0; i < nums.length; i++) {
// 如果对象里这个键对应的值已经是1了说明之前已经有相同的数字进来做键了
if (obj[nums[i]] === 1) {
// 这个时候从数组里把这个数拿掉
nums.splice(i, 1);
// 因为循环是用数组长度做判断,拿掉一个数字,就得回去一个
i--;
continue;
}
// 如果对象里这个键对应的值不是1,说明这个是新数字,放进对象里做键
obj[nums[i]] = 1;
}
// 返回所有键的长度
return Object.keys(obj).length;
}
用时:
Your runtime beats 6.17 % of typescript submissions
Your memory usage beats 5.03 % of typescript submissions (46 MB)
解法二:双指针
利用一快一慢指针,慢指针记录最终去重后的结果的数组的下标,快指针就是原本数组的下标。
每次循环,都会将快指针往前推进,可以就当遍历数组的时候用到的下标来看。
慢指针就是只有当有新的数字出现的时候才会往前推进,不是新的数字,慢指针都不会动。
但是什么时候赋值,肯定是新数字出现的时候,这个时候慢指针当前的数字肯定不能改,这个是之前认定的不同的数字,所以慢指针先加1,然后再复制
function removeDuplicates(nums) {
let slow = 0;
for (let fast = 1; fast < nums.length; fast++) {
// 如果快慢指针对应的数字不一致,慢指针就会动,先往前找一个新位置,然后把不一样的数字赋值进来
if (nums[fast] !== nums[slow]) {
slow++;
nums[slow] = nums[fast];
}
// 相同的情况下,慢指针不需要这个数字,因为它当前的数字就是这个值,所以只有快指针动
}
return slow + 1;
}
用时:
Your runtime beats 96.92 % of typescript submissions
Your memory usage beats 89.77 % of typescript submissions (44.3 MB)