Java 實現數組中的逆序對

在數組中的兩個數字,如果前面一個數字大於後面的數字,則這兩個數字組成一個逆序對,例如在數組{7,5,6,4}中,一共存在5對逆序對,分別是{7,6},{7,5},{7,4},{6,4},{5,4}。輸入一個數組,求出這個數組中的逆序對的總數P。並將P對1000000007取模的結果輸出。,即輸出P%1000000007。

代碼

解法一

暴力簡單低效,不會改變原數組

    public static int inversePairs(int[] array) {
        if (array == null || array.length < 2) {
            return 0;
        }
        int count = 0;
        for (int i = 0; i < array.length; i++) {
            for (int j = i + 1; j < array.length; j++) {
                if (array[i] > array[j]) {
                    count++;
                }
            }
        }
        return count % 1000000007;
    }

解法二

利用數組的歸併排序,高效,但是會改變原數組

    public static int inversePairs2(int[] array) {
        if (array == null || array.length < 2) {
            return 0;
        }
        int count = mergeSort(array, 0, array.length - 1);
        return count % 1000000007;
    }

    private static int mergeSort(int[] array, int start, int end) {
        if (start >= end) {
            return 0;
        }

        // 找到數組的中點,分割爲兩個子數組,遞歸求解
        int middle = (start + end) / 2;
        int left = mergeSort(array, start, middle);
        int right = mergeSort(array, middle + 1, end);

        // 存儲歸併後的數組
        int[] copy = new int[array.length];
        System.arraycopy(array, start, copy, start, end - start + 1);
        // 從兩個子數組的尾部開始遍歷
        int i = middle;
        int j = end;
        int copyIndex = end;
        // 記錄逆序對的數量
        int count = 0;

        while (i >= start && j >= middle + 1) {
            // 數組是升序的
            // 如果左邊數組比右邊數組大,則將大的放入存儲數組中
            // 並且累加逆序對,應爲是有序的,所以左邊數組的第i個元素比第j個及其之前的數都大
            if (array[i] > array[j]) {
                copy[copyIndex--] = array[i--];
                count += (j - middle);
            } else {
                copy[copyIndex--] = array[j--];
            }
        }

        // 將子數組剩餘的部分一次寫入歸併後的存儲數組
        while (i >= start) {
            copy[copyIndex--] = array[i--];
        }
        while (j >= middle + 1) {
            copy[copyIndex--] = array[j--];
        }

        // 將本次兩個子數組的合併寫入原數組中
        for (int k = start; k <= end ; k++) {
            array[k] = copy[k];
        }
        return left + right + count;
    }
發佈了107 篇原創文章 · 獲贊 40 · 訪問量 36萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章