劍指Offer Java版解題

3. 數組中重複的數字

題目一

  • 題目描述:

長度爲n的數組,全部數字都在0~n-1內。找出數組中的重複數字。如入參{2,3,1,0,2,5,3},對應重複數字爲2或者3。java

  • 解題思路:

要求時間複雜度O(N),空間複雜度O(1)。所以不能使用排序的方法,也不能使用額外的標記數組。數組

對於這種數組元素在[0, n-1]範圍內的問題,能夠將值爲i的元素調整到第i個位置上進行求解。spa

以(2, 3, 1, 0, 2, 5)爲例,遍歷到位置4時,該位置上的數爲2,可是第2個位置上已經有一個2的值了,所以能夠知道2重複。code

  • 代碼:
public static boolean findDuplicateNumber1(int[] array, int[] duplications) {
    if (array == null || array.length < 1) {
        return false;
    }
    int len = array.length;
    for (int i = 0; i < len; i++) {
        if (array[i] < 0 || array[i] > len) {
            return false;
        }
    }
    for (int i = 0; i < len; i++) {
        while (array[i] != i) {
            if (array[i] == array[array[i]]) {
                duplications[0] = array[i];
                return true;
            }
            int temp = array[i];
            array[i] = array[temp];
            array[temp] = temp;
        }
    }
    return false;
}
複製代碼

題目一

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

  • 解題思路: 不能修改原數組,能夠引入一個長度爲n的輔助數組,可是這樣的話空間複雜度要求O(n)。it

利用二分法的概念,以中間的數字m將1~n的分爲1~m和m+1~n兩部分,分別統計兩個範圍內的數字的個數,若是1~m的數字的數目超過m,則重複數字在m中;不然m+1~n的區間裏必定包含重複數字。而後繼續將m+1~n的區間拆分爲兩份,直到找到一個重複的數字。io

如數組{2,3,5,4,3,2,6,7},數字範圍爲1~7,分爲1~4和5~7兩段,1~4有5個,因此必定有重複數字;而後1~4分爲1~2和3~4兩段,1~2有2個,3~4有3個,因此3~4必定有重複數字;而後再分爲3和4兩段,3有兩次,即3爲重複數字。function

  • 代碼:
public static int findDuplicateNumber2(int[] array) {
    if (array == null || array.length < 1) {
        return -1;
    }
    int start = 1;
    int end = array.length - 1;
    while (start <= end) {
        int mid = (end - start) / 2 + start;
        int count = countRange(array, start, mid); //統計範圍內不一樣數字個數
        if (end == start) { //當只統計一個數字時,若是count>1就是重複數字
            if (count > 1) {
                return start;
            } else {
                break;
            }
        }
        if (count > (mid - start + 1)) {
            end = mid;
        } else {
            start = mid + 1;
        }
    }
    return -1;
}

private static int countRange(int[] array, int start, int end) {
    if (array == null) {
        return 0;
    }
    int count = 0;
    for (int i = 0; i < array.length; i++) {
        if (array[i] >= start && array[i] <= end) {
            count++;
        }
    }
    return count;
}
複製代碼
相關文章
相關標籤/搜索