内容简介:LeetCode - 026 - 删除排序数组中的重复项(remove-duplicates-from-sorted-array
Create by jsliang on 2019-06-06 11:11:26
Recently revised in 2019-06-06 14:30:57
一 目录
不折腾的前端,和咸鱼有什么区别
| 目录 | | --- | | 一 目录 | | 二 前言 | | 三 解题 | | 3.1 解法 - 双指针 | | 3.2 解法 - 违规操作 |
二 前言
难度:简单
涉及知识:数组、双指针
题目地址:https://leetcode-cn.com/problems/remove-duplicates-from-sorted-array/
题目内容:
给定一个 排序 数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。
不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。
示例 1:
给定数组 nums = [1,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。
你不需要考虑数组中超出新长度后面的元素。
说明:
为什么返回数值是整数,但输出的答案是数组呢?
请注意,输入数组是以“引用”方式传递的,这意味着在函数里修改输入数组对于调用者是可见的。
你可以想象内部操作如下:
// nums 是以“引用”方式传递的。也就是说,不对实参做任何拷贝
int len = removeDuplicates(nums);
// 在函数里修改输入数组对于调用者是可见的。
// 根据你的函数返回的长度, 它会打印出数组中该长度范围内的所有元素。
for (int i = 0; i < len; i++) {
print(nums[i]);
}
三 解题
官方题解:https://leetcode-cn.com/problems/remove-duplicates-from-sorted-array/solution/shan-chu-pai-xu-shu-zu-zhong-de-zhong-fu-xiang-by-/
解题千千万,官方独一家,上面是官方使用 Java 进行的题解。
小伙伴可以先自己在本地尝试解题,再看看官方解题,最后再回来看看 jsliang 讲解下使用 JavaScript 的解题思路。
3.1 解法 - 双指针
解题代码:
var removeDuplicates = function(nums) {
for (let i = 0; i < nums.length; i++) {
if (nums[i] === nums[i + 1]) {
nums.splice(i, 1);
i--;
}
}
};
执行测试:
nums
:[1,1,2]
return
:
2
LeetCode Submit:
✔ Accepted
✔ 161/161 cases passed (124 ms)
✔ Your runtime beats 72.77 % of javascript submissions
✔ Your memory usage beats 15.24 % of javascript submissions (37.6 MB)
知识点:
splice()
:splice()
方法通过删除或替换现有元素或者原地添加新的元素来修改数组,并以数组形式返回被修改的内容。此方法会改变原数组。splice()
详细介绍
解题思路:
首先,这道题涉及到所谓的 双指针 了,什么是 双指针 呢?
《LeetBook(LeetCode详解)》 - 双指针
双指针,顾名思义,就是利用两个指针去遍历数组,一般来说,遍历数组采用的是单指针(index) 去遍历,两个指针一般是在有序数组中使用,一个放首,一个放尾,同时向中间遍历,直到两个指针相交,完成遍历,时间复杂度也是O(n)。
啥意思咧?就好比我们的代码:
for (let i = 0; i < nums.length; i++) {
if (nums[i] === nums[i + 1]) {
nums.splice(i, 1);
i--;
}
}
在这里,我们是不是使用了数组的两个位置? [i]
以及 [i+1]
。
通过这两个指针的不断移动,直到把整个数组遍历一次,从而得到最终解。
然后,我们需要知道的是,由于代码中,我们使用了 for()
+ splice()
,从而造成的耗时和空间会比其他代码大,因为 splice()
是 JavaScript 封装好的方法。
是不是觉得无法理解?那么我们稍微看一眼 splice()
的源码吧:
仅仅看看就行了,这里不做过多讲解,刚兴趣的小伙伴可以前往 V8 引擎源码
function ArraySplice(start, delete_count) {
CHECK_OBJECT_COERCIBLE(this, "Array.prototype.splice");
var num_arguments = arguments.length;
var array = TO_OBJECT(this);
var len = TO_LENGTH(array.length);
var start_i = ComputeSpliceStartIndex(TO_INTEGER(start), len);
var del_count = ComputeSpliceDeleteCount(delete_count, num_arguments, len, start_i);
var deleted_elements = ArraySpeciesCreate(array, del_count);
deleted_elements.length = del_count;
var num_elements_to_add = num_arguments > 2 ? num_arguments - 2 : 0;
if (del_count != num_elements_to_add && %object_is_sealed(array)) {
throw %make_type_error(kArrayFunctionsOnSealed);
} else if (del_count > 0 && %object_is_frozen(array)) {
throw %make_type_error(kArrayFunctionsOnFrozen);
}
var changed_elements = del_count;
if (num_elements_to_add != del_count) {
// If the slice needs to do a actually move elements after the insertion
// point, then include those in the estimate of changed elements.
changed_elements += len - start_i - del_count;
}
if (UseSparseVariant(array, len, IS_ARRAY(array), changed_elements)) {
%NormalizeElements(array);
if (IS_ARRAY(deleted_elements)) %NormalizeElements(deleted_elements);
SparseSlice(array, start_i, del_count, len, deleted_elements);
SparseMove(array, start_i, del_count, len, num_elements_to_add);
} else {
SimpleSlice(array, start_i, del_count, len, deleted_elements);
SimpleMove(array, start_i, del_count, len, num_elements_to_add);
}
// Insert the arguments into the resulting array in
// place of the deleted elements.
var i = start_i;
var arguments_index = 2;
var arguments_length = arguments.length;
while (arguments_index < arguments_length) {
array[i++] = arguments[arguments_index++];
}
array.length = len - del_count + num_elements_to_add;
// Return the deleted elements.
return deleted_elements;
}
如上, splice()
先执行删除操作,删除指定个数的元素,然后再插入 elements
(元素或数组),他的每次删除都涉及大量元素的重新排列,而在插入元素时引入队列来管理。所以 splice()
的效率不高
最后,我们要做的就是返回数组的长度,就这样就 OK 了。
3.2 解法 - 违规操作
解题代码:
var removeDuplicates = function(nums) {
var a = [...new Set(nums)];
for (var i = 0;i < a.length;i++) nums[i] = a[i];
return a.length;
};
执行测试:
nums
:[1,1,2]
return
:
2
LeetCode Submit:
✔ Accepted
✔ 161/161 cases passed (112 ms)
✔ Your runtime beats 93.2 % of javascript submissions
✔ Your memory usage beats 45.6 % of javascript submissions (37.1 MB)
知识点:
Set
:Set
对象允许你存储任何类型的唯一值,无论是原始值或者是对象引用。Set
详细介绍
解题思路:
首先,jsliang 表示这种方法可能不符合题意,但是它又是可行的!所以不管怎么说,莽就对了~
然后, Set
对象会对值进行唯一操作,如果输入 [1,1,2]
,那么这个 Set
会变成 Set(2) {1,2}
: leta=newSet([1,1,2]);
。
接着,我们利用 ES6 的扩展运算符: [...newSet(nums)]
,可以直接将 Set
类型转换成 Array
类型。
最后,循环遍历 a
,将 a
的内容赋值到 nums
即可(注意, nums
后面还是会有一些乱七八糟的数据,不过它不影响我们的解题)。
jsliang 广告推送:
也许小伙伴想了解下云服务器
或者小伙伴想买一台云服务器
或者小伙伴需要续费云服务器
欢迎点击 云服务器推广 查看!
jsliang 的文档库 由 梁峻荣 采用 知识共享 署名-非商业性使用-相同方式共享 4.0 国际 许可协议进行许可。
基于https://github.com/LiangJunrong/document-library上的作品创作。
本许可协议授权之外的使用权限可以从 https://creativecommons.org/licenses/by-nc-sa/2.5/cn/ 处获得。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- JavaScript数组-排序算法
- 数组的去重和排序
- javascript 数组排序(sort,冒泡)
- Go 寻找数组中最小的 k 个数:全部排序和部分排序
- JS骚操作之数组快速排序
- 数组排序并插入值算法(JavaScript)
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。