(Java)leetcode-26 Remove Duplicates from Sorted Array(双指针)

题目

【删除有序数组中的重复元素】
Given a sorted array nums, remove the duplicates in-place such that each element appear only once and return the new length.

Do not allocate extra space for another array, you must do this by modifying the input array in-place with O(1) extra memory.

Example 1:

Given nums = [1,1,2],

Your function should return length = 2, with the first two elements of nums being 1 and 2 respectively.

It doesn’t matter what you leave beyond the returned length.
Example 2:

Given nums = [0,0,1,1,1,2,2,3,3,4],

Your function should return length = 5, with the first five elements of nums being modified to 0, 1, 2, 3, and 4 respectively.

It doesn’t matter what values are set beyond the returned length.
Clarification:

Confused why the returned value is an integer but your answer is an array?

Note that the input array is passed in by reference, which means modification to the input array will be known to the caller as well.

Internally you can think of this:

// nums is passed in by reference. (i.e., without making a copy)
int len = removeDuplicates(nums);

// any modification to nums in your function would be known by the caller.
// using the length returned by your function, it prints the first len elements.
for (int i = 0; i < len; i++) {
    print(nums[i]);
}

思路1

通常情况下删除元素意味着需要将该位置后面的所有元素进行前移,但是这样是比较耗费时间的,时间复杂度将达到O(n^2)。
本题的特殊性在于,修改后的数组是根据返回的int len 来截取的,也就是说,我们可以不通过移动元素来实现删除,我们只需要把应保留的元素覆盖之前“重复”元素即可。
[0,0,1,1,1,2,2,3,3,4]为例:
索引i首先移动到第二个0处,判断出后面没有更多的0了,此时变量dupNum为1,表示数组中有1个多余元素,那么就可以将第一个“1”覆盖掉第二个0(前移dupNum个单位),以达到“删除”的效果,此时的数组是这样的:[0,1,1,1,1,2,2,3,3,4]
接下来i继续移动,直到停留在nums[4]的1处,统计到有2个重复的1,此时变量dupNum为1+2=3,表示后面的2应该往前“移动”3位,此时的数组是这样的:
[0,1,2,1,1,2,2,3,3,4]
重复以上步骤,数组最后看起来是这样的:[0,1,2,3,4,2,2,3,3,4]
在上面过程中不断统计新的数组长度:5
那么截取后,新的数组为`[0,1,2,3,4]
时间复杂度O(n)

代码1

class Solution {
    public int removeDuplicates(int[] nums) {
        if(nums.length==0)
            return 0;
        int dupNum = 0;//数组中“多余”元素的数量
        int newLength = 1;//保存修改后数组的长度
        int i = 0;
        while(i < nums.length-1){
            while(nums[i] == nums[i+1]){//后边的元素与当前元素相同,则i后移直到停留在不同的元素之前
                dupNum++; //说明后边的元素是多余的
                i++;
                if(i == nums.length-1)//i到达数组的末尾则直接返回,避免越界
                    return newLength;
            }
            
            nums[i+1-dupNum] = nums[i+1]; //关键,向前替换掉对应位置的元素,而无需整体移动
            newLength++;
            i++;
     }
        return newLength;
    }
}

提交结果

Runtime: 5 ms, faster than 99.86% of Java online submissions for Remove Duplicates from Sorted Array.
Memory Usage: 40.3 MB, less than 87.27% of Java online submissions for Remove Duplicates from Sorted Array.

思路2

对上面的思路上进行改进,提高代码的阅读性,采用经典的“双指针法”,j指针负责遍历数组,i指针负责标志哪个位置上的元素应该被覆盖(相当于上面代码中的dupNum),因为被覆盖的位置是连续的,所以i每次自增1。

代码2

class Solution {
	public int removeDuplicates(int[] nums) {
	    if (nums.length == 0) return 0;
	    int i = 0;
	    
	    for (int j = 1; j < nums.length; j++) {
	        if (nums[j] != nums[i]) {
	            i++;
	            nums[i] = nums[j];
	        }
	    }
	    return i + 1;
	}
}

提交结果

Runtime: 5 ms, faster than 99.86% of Java online submissions for Remove Duplicates from Sorted Array.
Memory Usage: 41.4 MB, less than 66.99% of Java online submissions for Remove Duplicates from Sorted Array.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值