LeetCode刷题日记(简单)- 26. 删除有序数组中的重复项

97 阅读4分钟

前言

一个小伙伴说希望成立一个刷题小组,本就着富强、民主、文明、和谐,倡导自由、平等、公正、法治,倡导爱国、敬业、诚信、友善,积极培育社会主义核心价值观,我答应他了。

因为也没有刷过题,比较菜。然后就看了下别人家的孩子怎么刷题的,这里附上链接。

-力扣传送门-

朝花夕拾 - 2019 总结(附 283 道 LeetCode 题解)

我是如何刷 LeetCode 的?

题目描述:

给你一个 升序排列 的数组 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];
}

如果所有断言都通过,那么您的题解将被 通过

输入: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 。不需要考虑数组中超出新长度后面的元素。
/**
 * @param {number[]} nums
 * @return {number}
 * 经历过之前没读懂题意,导致答案无法通过,浪费了时间,所以我们一定要吸取教训,仔细读题。
 * 读题可知,我们需要对数组去重,并使用原数组内存操作。
 * 返回删除后数组长度,就是原数组减去重复元素个数。
 * 前部分是新去重数组,后面是重复数组元素丢弃区。
 * 因为不能使用额外数组空间,所以我们不能用js删除数组api了,这就很尴尬。
 * 本着写不出来看答案的优秀学习方法,我们了解到这道题要用到双指针中的快慢指针。
 * 
 */
/**
 * @description: 双指针   TC:O(n)  SC:O(1)
 * @param {*} nums 输入数组
 * @return {*}
 */
function removeDuplicates(nums){
    /**
     * 该方案利用双指针的方式,定义两个指针(low初值0,fast初值1),当两指针所指元素相同时,将fast指针继
     * 续向右移动直至遇到不同元素时(此时low与fast则会拉开一个区间,该区间的元素则为需要删除的相同的元
     * 素),将low指针向右移动一位,并将其赋值为fast指针所指元素(此时0到low指针所在区间的元素则是不重
     * 复的元素),当fast指针超出数组范围则终止循环,此时low位置+1则为去重后数组长度。
     */

    // 如果数组长度不大于1,无需去重直接返回即可
    if(nums.length<=1)return nums.length;
    // 定义两个指针
    let fastPoint=1,lowPoint=0;
    // 当fast指针超出数组范围则终止循环
    while(fastPoint<nums.length)
    {
        // 当两指针所指元素不同
        if(nums[lowPoint]!=nums[fastPoint])
        {
            // 将low指针向右移动一位
            lowPoint++;
            // 并将其赋值为fast指针所指元素
            nums[lowPoint]=nums[fastPoint];
        }
        // 继续移动fast指针
        fastPoint++;
    }
    return lowPoint+1;
}

我们平时都喜欢用遍历,其实最早我就想着遍历一次,重复的替换成标记,然后再次遍历把标记交换位置正向排序,遇到就是最大值。

双指针这个遍历一定没有想到吧。

我们看到图解

1631552114-iGjdpt-快慢指针.png