【剑指Offer】面试题3 数字中重复的数字——题目一:找出数组中重复的数字(Java)

题目一:找出数组中重复的数字

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


题解1:

思路:先将数字排序,然后遍历数组,找出重复的数字。(排序时间:O(nlogn))

代码实现:

    /*
    排序+遍历的方式找出数组中重复的数字
     */
    public static void duplicateNum(int []arr)
    {

        Arrays.sort(arr);
        for (int i=1;i<arr.length;i++)
            if (arr[i]==arr[i-1])
                System.out.println(arr[i]);
    }

题解2:

思路:构建一个哈希表,遍历数组所有数字,判断哈希表中是否存在这个数字,如果没有,则添加进哈希表。如果已经存在,则输出该值。

代码实现:

    public static void duplicateNum(int []arr)
    {

        HashMap hashMap = new HashMap();            //新建一个hashmap

        for (int i=0;i<arr.length;i++)              //遍历数组中的元素
        {

            //如果hash表中没有该数字,添加并以其本身作为关联键
            if (!hashMap.containsKey(arr[i]))       
                hashMap.put(arr[i],arr[i]);
            else   

             //如果存在该数字了,说明出现重复数字,则打印该数字
                System.out.println(arr[i]); 
        }             
        System.out.println(hashMap);

    }

题解3:

思路:由于题目中的数组中数字都在0~n-1范围内,所以在我们排序数组之后,如果这个数组中无重复数字(假设为{0,1,2,3,4,5,6}),那么数字arr[i]将会与其下标相同;一一对应成以下情况:

下标0123456
0123456

如果有重复数字(以题目中所给数组为例{0,1,2,2,3,3,5}),同样将其一一对应成以下情况:

下标0123456
0123null5null
   23   

出现了一些位置存在多个值,一些位置为空(null)。

而实际上排序的元素在数组中的对应情况应该是:

下标0123456
0122335

所以可以对原数组({2,3,1,0,2,5,3})进行检索,步骤如下:

① 从数组第0位开始检索,arr[0]=2,所以arr[0]!=0,则将其与下标为2的那个数交换位置,即arr[0](值为2)与arr[2](值为1)交换,得到新数组:{1,3,2,0,2,5,3}

② 新数组{1,3,2,0,2,5,3}第0位arr[0]=1,仍然有arr[0]!=0,则重复上一次操作,即arr[0](值为1)与arr[1](值为3)交换,得到新数组:{3,1,2,0,2,5,3}

③ 继续重复上一次操作,将arr[0](值为3)与arr[3](值为0)交换,得到新数组:{0,1,2,3,2,5,3}

④ 此时数组第0,1,2,3位置上的值arr[i]都与之下标i相同,直到下标为4时,值与下标不同了,arr[4]=2,当我们继续将其作交换操作时,我们发现arr[4](值为2)与arr[2](值为2)两者的值是相同的,此时我们就找到了第一个相同数字2,就可以输出其值,然后跳出此次循环,继续检索下一个位置。

⑤ 重复检索直到最后一个位置的数字完成时,程序结束。

代码实现:

    public static void duplicateNum(int []arr)
    {

        //判断数组是否为空
        if (arr==null||arr.length<1)
            return;

        //判断数组中数字是否满足0~n-1范围内的先决条件
        for (int i=0;i<arr.length;i++)
            if ( arr[i] < 0 || arr[i] > arr.length - 1)
            return;

        int temp=0;
        for (int i=0;i<arr.length;i++)
            while (arr[i]!=i)
            {
                if (arr[i]==arr[arr[i]])
                {
                    System.out.println(arr[i]);
                    break;
                }
                else
                    {
                    temp = arr[i];
                    arr[i] = arr[temp];
                    arr[temp] = temp;
                    }
            }

    }

PS:该解法只能在满足先决条件(所有数字满足在[0,n-1]范围内)时才实用,所以需要提前判断是否满足条件。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值