03_數組中的重複數字

題目:在一個長度爲n的數組裏的所有數字都在0到n-1的範圍內。數組中某些數字是重複的,但不知道有幾個數字是重複的。也不知道每個數字重複幾次。請找出數組中任意一個重複的數字。例如,如果輸入長度爲7的數組{2,3,1,0,2,5,3},那麼對應的輸出是重複的數字2或者3。
public class TestMethod3_1 {

    public static void main(String[] args) {
        int[] arr = {2, 3, 1, 0, 2, 5, 3};
        System.out.println("打印重複的數字=>" + method(arr));
    }

    public static int method(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 - 1) return -1;
        }

        for (int i = 0; i < arr.length; i++) {
            while (i != arr[i]) {
                if (arr[i] == arr[arr[i]]) return arr[i];
                swap(arr, i, arr[i]);
            }
        }
        return -1;
    }

    public static void swap(int[] arr, int a, int b) {
        int temp = arr[a];
        arr[a] = arr[b];
        arr[b] = temp;
    }
}
解題思路
  • 一維數組在內存空間佔用連續的空間,因此可以根據下標定位對應的元素,然後兩兩交換。
複雜度分析
  • 時間複雜度:O(n)
  • 空間複雜度:O(1)
題目:在一個長度爲n+1的數組裏的所有數字都在1到n的範圍內。所以數組中至少有一個數字是重複。請找出數組中任意一個重複的數字,但不能修改輸入的數組。例如:如果輸入長度爲7的數組{2,3,5,4,3,2,6,7},那麼對應的輸出是重複的數字2或者3。
public class TestMethod3_2 {

    public static void main(String[] args) {
        int[] arr = {2, 3, 1, 6, 2, 5, 3};
        System.out.println("二分法打印重複的數字=>" + method1(arr));
        System.out.println("龜兔賽跑算法打印重複的數字=>" + method2(arr));
    }

    /**
     * 二分法
     *
     * @param arr 待查找是否存在重複的數組
     * @return 返回數組中重複的數字,如果不存在重複返回-1
     */
    public static int method1(int[] arr) {
        if (arr == null || arr.length <= 0) return -1;
        for (int i = 0; i < arr.length; i++) {
            if (arr[i] < 1 || arr[i] > arr.length - 1) return -1;
        }

        int a1 = arr[0];
        int a2 = arr[0];

        while (true) {
            a1 = arr[a1];
            a2 = arr[arr[a2]];
            if (a1 == a2) break;
        }

        int p1 = arr[0];
        while (p1 != a1) {
            p1 = arr[p1];
            a1 = arr[a1];
        }
        return p1;
    }

    /**
     * 龜兔賽跑算法
     *
     * @param arr 待查找是否存在重複的數組
     * @return 返回數組中重複的數字,如果不存在重複返回-1
     */
    public static int method2(int[] arr) {

        // robust
        if (arr == null || arr.length <= 0)
            return -1;
        for (int i = 0; i < arr.length; i++)
            if (arr[i] < 1 || arr[i] > arr.length - 1)
                return -1;

        int start = 1;
        int end = arr.length - 1;
        while (start <= end) {
            // int mid = (start + end) / 2;
            int mid = ((end - start) >> 1) + start;

            // 對範圍內的元素個數進行計數
            int count = 0;
            for (int i = 0; i < arr.length; i++) {
                if (arr[i] <= mid && arr[i] >= start)
                    count++;
            }

            if (start == end) {
                if (count > 1)
                    return start;
                else
                    break;
            }

            // 根據檢測情況調整會出現重複的整數範圍
            if (count > mid - start + 1)
                end = mid;
            else
                start = mid + 1;
        }
        return -1;
    }
}
解題思路
  • 二分法查找法
  • 龜兔賽跑算法
複雜度分析
  • 方法一的時間複雜度:O(nlongn),方法二的時間複雜度:O(n)
  • 空間複雜度:O(1)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章