7. 删除有序数组中的重复项
给你一个 升序排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。
由于在某些语言中不能改变数组的长度,所以必须将结果放在数组nums的第一部分。更规范地说,如果在删除重复项之后有 k 个元素,那么 nums 的前 k 个元素应该保存最终结果。
将最终结果插入 nums 的前 k 个位置后返回 k 。
不要使用额外的空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。
判题标准:
系统会用下面的代码来测试你的题解:
int[] nums = [...]; // 输入数组
int[] expectedNums = [...]; // 长度正确的期望答案
int k = removeDuplicates(nums); // 调用
assert k == expectedNums.length;
for (int i = 0; i < k; i++) {
assert nums[i] == expectedNums[i];
}
示例 1:
输入:nums = [1,1,2]
输出:2, nums = [1,2,_]
解释:函数应该返回新的长度 2 ,并且原数组 nums 的前两个元素被修改为 1, 2 。
不需要考虑数组中超出新长度后面的元素。
示例 2:
输入:nums = [0,0,1,1,1,2,2,3,3,4]
输出:5, nums = [0,1,2,3,4]
解释:函数应该返回新的长度 5 , 并且原数组 nums 的前五个元素被修改为 0, 1, 2, 3, 4 。
不需要考虑数组中超出新长度后面的元素。
提示:
1 <= nums.length <= 3 * 104-104 <= nums[i] <= 104nums已按 升序 排列
思路: `nums` 已按升序排列, 在循环nums的时候 从第二个开始与第一个进行比较,
两者相同进行下一轮循环length待定,不相同length+1,并将后一个赋值给前一个
var removeDuplicates = function (nums) {
let length = 1;
for (let index = 1; index < nums.length; index++) {
if (nums[index] != nums[index - 1]) {
nums[length] = nums[index];
length++;
}
}
return length;
};
另一个思路:换一个角度思考,这个也就是去重,因为是顺序是已经排序好的,其实不用考虑相对位置的问题。去重完返回数组的长度即可。 考虑到去重最简单的方式就是,使用es6提出的Set数据结构的特性
var removeDuplicates = function(nums) {
let arr = new Set(nums);
nums.length = 0;
nums.push(...arr);
return nums.length
};
温馨提示
1.O(1)就是最低的时空复杂度了,也就是耗时/耗空间与输入数据大小无关,无论输入数据增大多少倍,耗时/耗空间都不变。
哈希算法就是典型的O(1)时间复杂度,无论数据规模多大,都可以在一次计算后找到目标(不考虑冲突的话)
2.时间复杂度为O(n),就代表数据量增大几倍,耗时也增大几倍。比如常见的遍历算法。
new Set(nums) 空间复杂度:O(m),m 为去重后的数组长度。
O(1)、O(2)、O(20) 这些都是常数级别空间复杂度和O(1)没有区别
还是那就话,我们不要在乎提交代码的效率,但是要思考不同的角度实现的思考