找出数组中的重复元素

Find All Duplicates in an Array Add to List

Description

Given an array of integers, 1 ≤ a[i] ≤ n (n = size of array), some elements appear twice and others appear once.

Find all the elements that appear twice in this array.

Could you do it without extra space and in O(n) runtime?

Example:
Input:

[4,3,2,7,8,2,3,1]

Output:

[2,3]

编者第一次看到这道题的时候,不假思索地采用了HashMap,结果一提交发现
114ms,位于Java程序员的后2%,说明这种算法是及其耗时的。
于是,编者开始寻找优化的算法:

一种巧妙的方法:

这种算法比较巧妙,就是在遍历数组nums的时候,对于每一个nums[i],找到nums[nums[i]-1],并将其取反,而如果nums[nums[i]-1] < 0的话,则说明nums[i]出现过,将其记录下来。
提交后,耗时14ms,较之前有极大的提升
该算法成立的前提条件是:

  1. 1 ≤ a[i] ≤ n (n = 数组的大小)
  2. 数组中的值出现的次数只能为1或2

也就是说,每个数组元素都能找到相对应的下标,所以可以将该下标对应的元素取反,即做一个标记。(当然,若是数组中的值出现次数为3的话,就无能为力了。)

附Java代码:

class Solution{
    public List<Integer> findDuplicates(int[] nums){
        if(nums == null || nums.length <=1 )
            return new ArrayList<Integer>();
        List<Integer> list = new ArrayList<>();
        for(int i = 0 ; i < nums.length ; i ++){
            if(nums[i] < 0){
                if(nums[-nums[i]-1] < 0){
                    //如果之前存在的话,直接add
                    list.add(-nums[i]);
                }else
                    //如果之前不存在,则做标记
                    nums[-nums[i]-1]*=-1;
            }else{
                if(nums[nums[i]-1] < 0){
                    //如果之前存在的话,直接add
                    list.add(nums[i]);
                }else
                    //如果之前不存在,则做标记
                    nums[nums[i]-1]*=-1;
            }
        }
        return list;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值