【剑指Offer-Java】数组中重复的数字

数组中重复的数字

题目描述

在一个长度为n的数组里的所有数字都在0到n-1的范围内。 数组中某些数字是重复的,但不知道有几个数字是重复的。也不知道每个数字重复几次。请找出数组中任意一个重复的数字。 例如,如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是第一个重复的数字2。

思路

法1:借助辅助空间:
HashMapkey:某元素,value:某元素出现的次数
统计出所有元素出现的次数,最后找到一个次数>1的元素赋给duplication[0]
(题目只要任意一个重复元素,统计出所有的显然没有必要,所以需要寻找更好的方法)
法2:不借助辅助空间
数组所有元素范围都是0~n-1,数组长度就是n
所有如果数组中没有重复元素的话,数组排序后数字i肯定出现在下标为i的位置
若存在重复元素,则有些位置可能存在多个元素,有些位置上没有元素

  1. 从头扫描数组中每个数字
  2. 把下标为i的元素记为m,比较m和下标i。
    若m和下标i相等,就继续向后遍历
    若不相等,就把m和下标为m的元素比较
    (1)若m和下标为m的元素相等,说明该元素在下标为i和m的位置都出现了,找到了一个重复元素
    (2)若m和下标为m的元素不等,就把两元素交换,把m放到它应该待的位置上

实现

法1:借助辅助空间:

import java.util.HashMap;
public class Solution {
    public boolean duplicate(int numbers[],int length,int [] duplication) {
        HashMap<Integer,Integer> m=new HashMap<>();
        //边遍历数组,边加进去元素:<key:某元素,value:某元素出现的次数>
        for(int i=0;i<length;i++){
            if(!m.containsKey(numbers[i])){   //m里没有某元素,加进去,次数计为1
                m.put(numbers[i],1);
            }
            else{                             //m里有某元素,先获取已有的出现次数,再加上1
                int count=m.get(numbers[i]);
                m.put(numbers[i],count+1);   //key相同时,新value覆盖原value
            }
        }
        //寻找value大于1的某个元素
        for(int i=0;i<length;i++){
            if(m.get(numbers[i])>1){
                duplication[0]=numbers[i];
                return true;
            }
        }
        return false;
        
    }
}

法2:


public class Solution {
    
    public boolean duplicate(int numbers[],int length,int [] duplication) {
        /*数组所有元素范围都是0~n-1,数组长度就是n
        所有如果数组中没有重复元素的话,数组排序后数字i肯定出现在下标为i的位置
        若存在重复元素,则有些位置可能存在多个元素,有些位置上没有元素
        */
        //特殊情况
        if(numbers==null || length<=0) return false;
        //从头扫描数组中每个数字
        for(int i=0;i<length;i++){
            int m=numbers[i];   //把下标为i的元素记为m
            //若m和下标i相等,就继续向后遍历
            //若不相等,就把m和下标为m的元素比较
            while(m!=i){
                //若m和下标为m的元素相等,说明该元素在下标为i和m的位置都出现了,找到了一个重复元素
                if(m==numbers[m]){
                    duplication[0]=m;
                    return true;
                }
                //若m和下标为m的元素不等,就把两元素交换,把m放到它应该待的位置上
                else{
                    int temp=m;       
                    m=numbers[temp];       //直接写numbers[m]会超时,需要嵌套计算
                    numbers[temp]=temp;    //直接写numbers[temp]效率高,因为temp在上一步得到了,是一个已知的确定值
                }
            }
        }
        return false;
    }
}

Notes:交换numbers[i]和numbers[numbers[i]],不能直接写numbers[numbers[i]],因为这需要嵌套计算,会超时
可以用交换第一步的temp来代替numbers[i],因为第一步temp就算出来了,是个确定值,所以下一步再用时就剩一层计算了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值