听风是风

学或不学,知识都在那里,只增不减。

导航

JS leetcode 删除排序数组中的重复项 题解分析

壹 ❀ 引

一日一题,今天的题目来自于leetcode26. 删除排序数组中的重复项,其实在之前我们已经做了一道类似的题目,可参考JS leetcode 移除元素 题解分析,关于本题描述如下:

给定一个排序数组,你需要在 原地 删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。

不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 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。

你不需要考虑数组中超出新长度后面的元素

我们先来简单分析题目,再给出解题思路。

贰 ❀ 解题思路

经过leetcode算法题移除元素的教育,这次解题得额外抓住两个重点:

第一,题目真正的要求是获取不重复元素的长度,所以即使不删除重复元素也是允许的。

第二,不需要考虑数组中超出新长度后的元素,这句话的意思其实已经暗示,我们可以将不重复的元素集中在数组前面,后面的重复元素可以不管,比如

[1,2,2,3] => [1,2,3,2] 返回3,因为不重复的元素为 1,2,3

当然,我们可以先站在删除重复元素的角度来思考这个问题,这对于前端开发者来说更容易接受,直接上代码:

/**
 * @param {number[]} nums
 * @return {number}
 */
var removeDuplicates = function (nums) {
    for (var i = 0; i < nums.length;) {
        if (nums.indexOf(nums[i]) !== i) {
            nums.splice(i, 1);
        } else {
            i++;
        };
    };
    return nums.length;
};

思路很简单,因为indexOf获取的都是每个元素第一次出现的问题,所以只要当前元素的i不是第一次出现,那就说明是重复元素,利用splice删除执行元素即可。

而站在不删除元素的角度,这就得利用双指针进行元素覆盖,我们先上代码,再解释原理:

/**
 * @param {number[]} nums
 * @return {number}
 */
var removeDuplicates = function (nums) {
    if(nums.length === 0){
        return 0;
    };
    var s = 0, //慢指针,每赋值一次,慢指针往右移动一位
        f = 1, //快指针,只要重复就往右移动一位
        len = nums.length;
    for (; f < len; f++) {
        if (nums[s] !== nums[f]) {
            nums[s + 1] = nums[f];
            s++;
        };
    };
    return s + 1;
};

我们以[1,1,2,3]为例,注意,题目已经说了数组为已排序数组,所以相同元素必定相邻。

我们指定2个指针,慢指针s(slow)与快指针f(fast),慢指针主要负责当元素不同时进行赋值,快指针主要负责数组遍历,对每个元素进行比较。

说到底,就是每次比较完成之后,只要这个元素没重复,就把这个元素通过赋值的形式,依次排在s指针索引的后面;若比较相同就啥都不干,直接让快指针继续往后移动。

我们通过图解,来模拟[1,1,2,3]的赋值过程:

可以看到,一开始由于s为0,f为1,进行了第一次比较,如果相同,s作为起点元素保持不变,f作为快指针继续寻找下个比较目标;

而只要s与f的元素不同,则将f的元素复制到s的后一位,以此类推,由于s的索引是0,经过几次复制自增几次,最后获取的长度需要额外加1,大致上就是这个思路。

我最开始也是绕了半天,但是通过图解,真是感叹双指针的微妙之处。

当然,双指针代码处的if操作其实也可以改写成如下形式,思路是一样的,不过我还是认为上述写法好理解一点,先赋值,s再移动:

if (nums[s] !== nums[f]) {
    s++;
    nums[s] = nums[f];
};

那么关于本题的分析就到这里了。

posted on 2020-06-04 23:04  听风是风  阅读(1278)  评论(0编辑  收藏  举报