數組中的逆序對(Java實現)


來源:劍指offer

逆序對定義:a[i]>a[j],其中i<j

思路:利用歸並排序的思想,先求前面一半數組的逆序數,再求后面一半數組的逆序數,然后求前面一半數組比后面一半數組中大的數的個數(也就是逆序數),這三個過程加起來就是整體的逆序數目了。

易錯點:第二個方法在歸並時,需要array的左右子數組是已排好序的數組,歸並的結果是得到排好序的數組copy。因此在遞歸調用iPairs時,方法的前2個參數是顛倒的,這樣得到的array才是排好序的。

比如第一次時用copy當輔助數組對array排序,第二次就正好反過來。

代碼:

package algorithm;

public class InversePairs {

    public static int iPairs(int[] array) {
        if (array == null)
            throw new IllegalArgumentException();
        // 創建輔助數組
        int length = array.length;
        int[] copy = new int[length];
        System.arraycopy(array, 0, copy, 0, length);
        int numberOfInversePairs = iPairs(array, copy, 0, length - 1);
        return numberOfInversePairs;
    }

    /**
     * @author Thanos
     * @param array 未歸並數組 
     * @param copy 用於存儲歸並后數據的數組
     * @param begin 起始位置
     * @param end 結束位置
     * @return 逆序數
     */
    public static int iPairs(int[] array, int[] copy, int begin, int end) {
        if(begin == end)
            return 0;
        int mid = (begin + end) / 2;
        // 遞歸調用
        int left = iPairs(copy, array, begin, mid);
        int right = iPairs(copy, array, mid + 1, end);
        // 歸並
        int i = mid, j = end, pos = end;
        int count = 0; // 記錄相鄰子數組間逆序數
        
        while(i >= begin && j >= mid + 1)
        {
            if(array[i] > array[j]) {
                copy[pos--] = array[i--];
                count += j - mid;
            } else
                copy[pos--] = array[j--];
        }
        
        while(i >= begin)
            copy[pos--] = array[i--];
        while(j >= mid + 1)
            copy[pos--] = array[j--];
        
        return left + right + count;
    }

    public static void main(String... args) {
        int test[] = { 7, 5, 1, 6, 4 };
        int count = iPairs(test);
        System.out.println(count + " ");
    }

}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM