zoukankan      html  css  js  c++  java
  • JS Leetcode 26. 删除有序数组中的重复项 题解分析,字典与快慢双指针

    壹 ❀ 引

    本题来自LeetCode26. 删除有序数组中的重复项,是一道简单题,题目描述如下:

    给你一个有序数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。

    不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。

    说明:

    为什么返回数值是整数,但输出的答案是数组呢?

    请注意,输入数组是以「引用」方式传递的,这意味着在函数里修改输入数组对于调用者是可见的。

    你可以想象内部操作如下:

    // nums 是以“引用”方式传递的。也就是说,不对实参做任何拷贝
    int len = removeDuplicates(nums);

    // 在函数里修改输入数组对于调用者是可见的。
    // 根据你的函数返回的长度, 它会打印出数组中 该长度范围内 的所有元素。
    for (int i = 0; i < len; i++) {
    print(nums[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 。不需要考虑数组中超出新长度后面的元素。
    

    提示:

    • 0 <= nums.length <= 3 * 104
    • -104 <= nums[i] <= 104
    • nums 已按升序排列

    其实在去年,我已经做过了这道题的2.0版本并记录过题解JS Leetcode 80. 删除有序数组中的重复项 II题解,那么今天的这道题我们就快速过一遍,那么开始。

    贰 ❀ 字典

    其实不管数组是不是有序,我们都可以用一个字典用于记录已经出现的数字,如果它第一次出现,记录为true,反之如果已经被记录过,那么直接将当前数字从数组中剔除掉,思路很清晰,直接实现:

    /**
     * @param {number[]} nums
     * @return {number}
     */
    var removeDuplicates = function (nums) {
        let dic = {};
        let i = 0;
        while (i < nums.length) {
            // 如果为true,说明已存在,剔除数字
            if (dic[nums[i]]) {
                nums.splice(i, 1);
            } else {
                // 反之设置为true,让i自增
                dic[nums[i]] = true;
                i++;
            };
        };
        return nums.length;
    };
    

    叁 ❀ 快慢双指针

    其实在我上面贴的此题的2.0版本题解中也介绍了这种方法,当然支撑快慢指针的原因是因为题目中说了,不需要考虑数组中超出新长度后面的元素,也就是说:

    [1,1,2,2,3]
    //转为
    [1,2,3,2,3]
    

    我们只要保证转换完成的数组的前几位是符合题目要求的,后面超出的部分可以不需要管。

    而双指针的做法,在于需要一个快指针和一个慢指针,慢指针总是在符合条件后修改当前指针的数字,之后才会自增,只要不符合它就原地不同,而快指针会从头到尾扫描一遍,目的是不断找下一个元素和慢指针所在的元素进行对比,这样才能让两个指针按照某种约定慢慢右移,而当完成转换之后,慢指针一定会指向最后一个合法的数字,所以返回慢指针就是最终答案了。

    但需要注意的是,题目说最终允许X个相同数字存在时,那么数组前X个数字是不需要进行筛选的,这个逻辑会比较绕,我先贴上代码,再分析过程:

    /**
     * @param {number[]} nums
     * @return {number}
     */
    var removeDuplicates = function (nums) {
      	//定义可复用的函数,题目允许几个相同数字存在,x就是几
        function process(nums, x) {
            // 这里的s就是慢指针
            let s = 0
            // 这里的i是快指针
            for (let i = 0; i < nums.length; i++) {
                // s<x是因为前x个数字一定满足条件,满足前者即可,而只有超过了x个,才会走后面的判断看数字是否相等
                if (s < x || nums[s - x] !== nums[i]) {
                    nums[s] = nums[i]
                    s++;
                };
            };
            return s;
        };
    		// 根据提议,x是1,最多允许1个相同数字存在
        return process(nums, 1)
    
    };
    

    我们以数组[1,1,2,2,3]为例,这个过程就像这样:

    那么本篇文章就记录到这里了。

  • 相关阅读:
    37. Sudoku Solver(js)
    36. Valid Sudoku(js)
    35. Search Insert Position(js)
    34. Find First and Last Position of Element in Sorted Array(js)
    33. Search in Rotated Sorted Array(js)
    32. Longest Valid Parentheses(js)
    函数的柯里化
    俞敏洪:我和马云就差了8个字
    vue路由传值params和query的区别
    简述vuex的数据传递流程
  • 原文地址:https://www.cnblogs.com/echolun/p/14691420.html
Copyright © 2011-2022 走看看