初阶算法——删除有序数组中的重复项

题目

给你一个升序排列的数组 nums,请你原地删除重复出现的元素,使每个元素只出现一次,返回删除后数组的新长度。元素的相对顺序应该保持一致 。

由于在某些语言中不能改变数组的长度,所以必须将结果放在数组nums的第一部分。更规范地说,如果在删除重复项之后有 k 个元素,那么 nums 的前 k 个元素应该保存最终结果。

将最终结果插入 nums 的前 k 个位置后返回 k 。

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

解法一

看到这种删除数组中元素的问题我们首先想到的是遍历数组,将要删除位置后面的元素前移覆盖。实现这种思想最直接的方法就是两重for循环嵌套,一层负责遍历,一层负责前移。

但是我们知道,一般算法的时间复杂度 >= O(n^{2})就不太好了,而该算法的时间复杂度就是O(n^{2}),那么是否有更优的算法呢? 

class Solution {
    public int removeDuplicates(int[] nums) {
        int len = nums.length;
        for(int i = 0;i < len - 1;i++){    //遍历数组
            if(nums[i] == nums[i+1]){
                for(int j = i+1;j < len - 1;j++){    //覆盖前移
                    nums[j] = nums[j+1];
                }
                len--;    //数组长度-1
                i--;    //下一个元素继续与本元素比较,用i--抵消i++
            }
        }
        return len;
    }
}

解法二——双指针法

这里我不做过多解释,看LeeCode给出的官方动图解就一目了然了

删除排序数组中的重复项 - 删除有序数组中的重复项 - 力扣(LeetCode)

 该方法处理只需要一个循环语句,所以复杂度仅仅为O(n),远小于我们的第一种方法!

class Solution {
    public int removeDuplicates(int[] nums) {
        int head = 1,tail = 0;
        if(nums.length < 2)
            return nums.length;
        while(head < nums.length){
            if(nums[head] != nums[tail]){
                tail++;
                nums[tail] = nums[head];
            }
            head++;
        }
        return tail+1;    //因为对于tail指针是先移动再赋值,所以长度等于末尾值+1
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值