leetcode: T80. 删除有序数组中的重复项 II

题目描述

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

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/remove-duplicates-from-sorted-array-ii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解法1

由于该题限制了空间复杂度为O(1), 因此无法借助第二个临时数组来保存剔除之后的结果。由此我们很容易想到的一个解法就是 每 次 将 待 删 除 的 数 字 移 动 到 数 组 末 尾 , 并 且 将 数 组 长 度 减 小 \color{red}{每次将待删除的数字移动到数组末尾,并且将数组长度减小} 这样直接返回处理之后的数组长度即可。AC代码如下:

public int removeDuplicates(int[] nums) {
        int len = nums.length;
        if(len < 3) return len;
        for(int i = 0;i<len-2;){
            if(nums[i] == nums[i+2] ){ // 移除第一个
                int temp = nums[i];
                for(int j = i;j<len - 1;j++){
                    nums[j] = nums[j+1];
                }
                nums[len-1] = temp;
                len = len - 1;
                continue;
            }
            i++;
        }
        return len;
    }

通过分析代码可以得知,这种做法的时间复杂度为 O ( n 2 ) O(n^2) O(n2) ,空间复杂度为 O ( 1 ) O(1) O(1)
这个时间复杂度实属感人 (>_<) ,因此可以通过以下方式进行改进。

解法二

延续解法一的思路,在该算法下,总体思路没法进行改进,能够改进的就只有数组移动这个部分了。而且,这个算法的大部分时间都是花在数组移动上了。因此我们在数组移动上动动手脚。
具 体 方 案 : \color{red}{具体方案:} : 通过解法一可以得知,我们需要将[i+1,n] 上的内容移动到[i,n-1] 上,因此我们可以直接使用系统自带的数组拷贝方法。
值得注意的是:系统自带的 System.arrayCopy()native 方法,因此该方法是通过c++ 来实现,具有更好的效率

这个解法在OJ上的时间为 1ms, 解法一的时间为2ms.

public int removeDuplicates(int[] nums) {
        int len = nums.length;
        if(len < 3) return len;
        for(int i = 0;i<len-2;){
            if(nums[i] == nums[i+2] ){ // 移除第一个
                int temp = nums[i];
                if (len - 1 - i >= 0) System.arraycopy(nums, i + 1, nums, i, len - 1 - i);
                nums[len-1] = temp;
                len = len - 1;
                continue;
            }
            i++;
        }
        return len;
    }

解法三

上述的解法都是基于数组移动来解决的,该解法的虽然通过数组拷贝等方式改进,但是时间复杂度依旧比较高。除了上述解法,该题还可以通过快慢指针来解题,使用快慢指针之后,时间复杂度为O(n).
代码如下:

public int removeDuplicates2(int[] nums){
        int len = nums.length;
        if(len < 3) return len;
        int slow = 2,fast = 2;
        while(fast<len){
            if(nums[slow-2] != nums[fast]){
                nums[slow] = nums[fast];
                slow++;
            }
            fast++;
        }
        return slow;
    }

你可能感兴趣的:(leetcode,双指针,算法,leetcode)