「算法学习」:删除有序数组中的重复项

给你一个 升序排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。不要使用额外的空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。

题目来源:力扣(LeetCode)

输入:nums = [1,1,2]
输出:2, nums = [1,2,_]
解释:函数应该返回新的长度 2 ,并且原数组 nums 的前两个元素被修改为 1, 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,则数组不包含任何元素,因此返回0。当数组的长度大于0 时,数组中至少包含一个元素,在删除重复元素之后也至少剩下一个元素,因此数组第一个元素保持原状即可,从下标 1 开始删除重复元素。

定义两个指针 fast 和 slow 分别为快指针和慢指针,快指针表示遍历数组到达的下标位置,慢指针表示下一个不同元素要填入的下标位置,初始时两个指针都指向下标1。设数组的长度为n。将快指针fast 依次遍历从 1 到 n−1 的每个位置,对于每个位置,如果[fast]和[fast-1]元素不相等说明[fast] 和之前的元素都不同,因此将 [fast] 位置的值复制到[slow],然后将 slow 的值加 1,即指向下一个位置。

var removeDuplicates = function(nums) {
    const n = nums.length;
    //如果数组长度为0则直接返回
    if (n === 0) {
        return 0;
    }
    //设置fast、slow两个指针,
    let fast = 1, slow = 1; //保留至少一个元素,故初始值设为1
    //当fast小于数组长度时候遍历数组
    while (fast < n) {
    	//当fast指向的元素不与前一元素相同时候,将其赋值给slow指针指向的重复元素位置
        if (nums[fast] !== nums[fast - 1]) {
            nums[slow] = nums[fast];
            //赋值完后,slow指针往前走
            ++slow;
        }
        //当前元素出现多个重复的时候往前遍历
        ++fast;
    }
    //返回的slow指标就是去重后数组的长度
    return slow;
};

拓展:

给你一个有序数组 nums ,请你 原地 删除重复出现的元素,使每个元素 最多出现两次 ,返回删除后数组的新长度。不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。
题目来源:[力扣(LeetCode)]

可以看到此题是上面题目的拓展,思路都是一样的,只是判断条件稍作修改就可以解决此类拓展的问题

var removeDuplicates = function(nums) {
    const n = nums.length;
    //有序的数组决定了数组长度少于2时候直接返回
    if (n <= 2) {
        return n;
    }
    //因为保留两个重复的元素,初始值下标直接设为2
    let slow = 2, fast = 2;
    while (fast < n) {
    /*因为保留两个重复的元素,所以判断slow指向元素的上上个元素是否和当前fast元素相同来决定
    是否保留fast指向的元素,当slow-2指向元素与当前fast指向元素相同则数组slow前已有不重复的两个元素
    此时fast往下寻找不重复的元素*/
        if (nums[slow - 2] != nums[fast]) {
        //如果nums[slow-2]==nums[fast],则有nums[slow-2]==nums[slow-1]==nums[slow]==nums[fast]
            nums[slow] = nums[fast];
            ++slow;
        }
        ++fast;
    }
    //遍历完成后slow即是去重后数组长度
    return slow;
};

你可能感兴趣的:(算法,算法,学习,leetcode)