劍指offer第二版面試題2:數組中重複的數字(JAVA版)

題目:在一個長度爲n+1的數組裏的全部數字都在1~n的範圍內,因此數組中至少有一個數字是重複的。請找出數組中任意一個重複的數字,可是不能修改輸入的數組。例如,若是輸入長度爲8的數組{2,3,5,4,3,2,6,7},那麼對應的輸出是重複的數字2或者3。數組

 

方法1:利用輔助函數,逐一把原數組的每一個數字複製到輔助數組。若是原數組中被複制的數字是m,則把它複製到輔助數組中下標爲m的位置。若是下標爲m的位置上已經有數字了,則說明該數字重複了。因爲使用了輔助空間,故該方案的空間複雜度是O(n) 函數

public class Test1 {
    public static int getReNum(int[] arr){
        //傳入參數出錯
        if(arr==null || arr.length==0){
            return -1;
        }
        for(int i=0;i<arr.length;i++){
            if(arr[i]<=0 || arr[i]>arr.length){
                return -1;
            }
        }
        //輔助數組
        int[] temp=new int[arr.length];
        for(int i=0;i<arr.length;i++){
            if(temp[arr[i]]==arr[i]){
                return arr[i];
            }else{
                temp[arr[i]]=arr[i];
            }
        }
        return -1;
    }
    
    public static void main(String[] args) {
        int arr[]=new int[]{5,4,3,6,2,1,2};
        int reNum = getReNum(arr);
        System.out.println(reNum);
    }
}

方法二:相似二分法spa

  因爲分析一的空間複雜度是O(n),所以咱們須要想辦法避免使用輔助空間。咱們能夠這樣想:若是數組中有重複的數,那麼n+1個1~n範圍內的數中,必定有幾個數的個數大於1。那麼,咱們能夠利用這個思路解決該問題。咱們把從1~n的數字從中間的數字m分爲兩部分,前面一半爲1~m,後面一半爲m+1~n。若是1~m的數字的數目等於m,則不能直接判斷這一半區間是否包含重複的數字,反之,若是大於m,那麼這一半的區間必定包含重複的數字;若是小於m,另外一半m+1~n的區間裏必定包含重複的數字。接下來,咱們能夠繼續把包含重複的數字的區間一分爲二,直到找到一個重複的數字。code

public class Test2 {
    //傳入一個數組,從開始位置和結束位置,有多少個數字
    public static int getCount(int arr[],int start,int end){
        int count=0;
        for(int i=0;i<arr.length;i++){
            if(arr[i]>=start && arr[i]<= end){
                count++;
            }
        }
        return count;
    }
    //查找重複的數字
    public static int getReNum(int arr[]){
        //傳入數組不合法
        if(arr.length==0 || arr==null){
            return -1;
        }
        for(int i=0;i<arr.length;i++){
            if(arr[i]<=0 || arr[i]>=arr.length){
                return -1;
            }
        }
        
        int start=1;
        int end=arr.length-1;
        int mid=0;
        int count=0;
        while(end>=start){
            if(start==end){
                count=getCount(arr, start, end);
                if(count>1){
                    return start;
                }else{
                    break;
                }
            }
            mid = (start + end) / 2;
            count = getCount(arr, start, mid);
            if (count > mid - start + 1) {
                end = mid;
            } else {
                start = mid + 1;
            }
        }
        return -1;
    }
    
    public static void main(String[] args) {
        int[] numbers = { 1, 3, 5, 4, 2, 1, 6, 7 };
        int reNum = getReNum(numbers);
        System.out.println(reNum);
    }
}
相關文章
相關標籤/搜索