【剑指offer第2版-第4题-JAVA】

题目:不修改数组找出重复数字

题目:不修改数组找出重复数字,在一个长度为n+1的数组里的所有数字都在1~n的范围内,所以数组至少有一个数字是重复的。请找出数组中任意一
个重复的数字,但不能修改输入的数组,例:长度为8的数组{2,3,5,4,3,2,6,7},那么对应的输出应该是重复的数字2或者3.

第一时间想到借助辅助空间,创建同等长度的数组,已知长度为n,数字范围1~n+1,设定原数组nums[],新数组ans[],即将原数组的值放入对应新数组下标的位置上,例子:原数组第一个值2,赋值新数组ans[2]=2,上代码。

public static Integer getRepeatingNum(int nums[]){
        //判空,临界情况
        if(nums==null  || nums.length==0){
            return null;
        }
        //int空数组初始化默认值为0,Integer为null;
        Integer ans[] = new Integer[nums.length];
        for(int i=0;i<nums.length;i++){
            int temp = nums[i];
            //初始值为null,非初始值则代表已存放过,即重复数字
            if(ans[temp]!=null){
                return ans[temp];
            }
            //将对应的数值防止对应下标位,6->ans[6]
            ans[temp] = nums[i];
        }
        return null;
    }

官方解法:核心思想是二分查找,1~n的数组,设定中间数字m,分为1~m,m+1~n两部分,如果1~m的数字数量超过m,那么这一半的区间一定包含重复数字,否则另一半m+1~n包含重复数字,然后继续对包含重复数字的区间一分为二,直至找到重复数字为准。
例:{2,3,5,4,3,2,6,7}
长度为8,所有数字均在1~7的范围,中间数字是4,统计1,2,3,4(1~m)这四个数字在数组出现的次数,它们出现了5次,因此这四个数字中必定含有重复数字。上代码。

   //统计数组数字出现的次数
   public static int countRange(int temps[],int length,int start,int end){
        if(temps == null){
            return 0;
        }
        int count = 0;
        for (int i=0;i<length;i++){
            //统计start至end这个范围内,数组中数字出现的个数,例:理论上1~4,应该是4,如大于4则代表有重复数字
           if(temps[i]>=start && temps[i]<=end){
                ++count;
            }
        }
        return count;
    }
    public static Integer getRepeatingNumNew(int nums[],int length) {
        //判空,临界情况
        if (nums == null || nums.length == 0) {
            return null;
        }
        int start =1;
        int end = nums.length-1;
        while(end>=start){
            int middle = (end-start)/2+start;
            int count = countRange(nums,length,start,middle);
            if(end == start){
                if (count>1){
                    return start;
                }
                break;
            }
            if(count>(middle-start+1)){
                end = middle;
            }else {
                start = middle + 1;
            }
        }
        return -1;
    }

总结:

  1. 面试官的要求一定要听清楚
  2. 编写代码,注意方法变量命令规范(英文语义,大小写),判空,临界条件,不能只考虑正常情况
  3. 先实现出自己能写出来的,后面再考虑其他解法
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值