[Offer] [3-2] [array is not modified to identify duplicate numbers]

Title Description

  In an array of length n + 1, where all numbers are in the range of 1 ~ n, so that at least one number in the array is repeated. Please find an array of any one of the duplicate numbers, but can not modify the input array. For example, if the length of the input array of 8 {2,3,5,4,3,2,6,7}, then the corresponding output is repeatable number 2 or 3.
  

Ideas analysis

  Title array of length n + 1, and the range of numbers 1 ~ n, an array described there must duplicate numbers may be utilized to find a way similar to binary, the 1 ~ nnumeral is divided into two halves one half 1 ~ mthe other half m+1 ~ n, the scanning array, the array Statistics number that appears in the 1 ~ mnumber of times, and if the number is greater than mis described, duplicate numbers in 1 ~ mbetween, otherwise change the duplicate numbers in m+1 ~ nbetween.

Java code

public class Offer003_02 {
    public static void main(String[] args) {
        int[] arr = {1,9,4,4,3,2,6,7,7};
        int dupNum = Offer003_02.getDuplication(arr);
        System.out.println(dupNum);
    }
    
    public static int getDuplication(int[] arr) {
        return Solution1(arr);
    }
    
    /**
     * 由于题目中说明 数组长度为n+1,而数组中数字的范围为1~n, 这就说明数组中一定存在重复的数字
     * 将数字1 ~ n 切成两半:1 ~ m  、  m+1 ~n 
     * 可以判断 数组中数字在两个 范围中出现的次数,
     * 如果出现的次数大于 m , 则说明 重复的数字在1 ~ m 之间,否则,m+1 ~ n之间
     * 
     * 类似于二分查找的方法
     * 
     * @param arr
     * @return
     */
    private static int Solution1(int[]arr) {
        if(arr==null || arr.length<=0) {
            return -1;
        }
        int start = 1;
        int end = arr.length-1;
        while(end>=start) {
//          int middle = ((end-start)>>1) + start;
            int middle = (end+start)>>1;
            int count = getCount(arr,start,middle);
            if(end==start) {
                if(count > 1) {
                    return start;
                }else {
                    break;
                }
            }
            if(count > (middle-start)+1) {
                end = middle;
            }else {
                start = middle+1;
            }
        }
        return -1;
    }
    /**
     * 判断 arr  在start 和end 范围 内 有多少个元素
     * @param arr
     * @param start
     * @param end
     * @return
     */
    private static int getCount(int[] arr, int start, int end) {
        if(arr==null) {
            return 0;
        }
        int count = 0;
        for(int i=0;i< arr.length;i++) {
            if(arr[i]>=start&& arr[i]<=end) {
                ++count;
            }
        }
        return count;
    }   
}

Code link

Offer to prove safety codes -Java

Guess you like

Origin www.cnblogs.com/haoworld/p/boffer32-bu-xiu-gai-shu-zu-zhao-chu-zhong-fu-de-sh.html