1. 程式人生 > >【Java】 劍指offer(51)數組中的逆序對

【Java】 劍指offer(51)數組中的逆序對

邊界 時間復雜度 return tps arr 暫時 大小 target star

本文參考自《劍指offer》一書,代碼采用Java語言。

更多:《劍指Offer》Java實現合集

題目 

  在數組中的兩個數字如果前面一個數字大於後面的數字,則這兩個數字組成一個逆序對。輸入一個數組,求出這個數組中的逆序對的總數。

思路

  如果遍歷數組,對每個數字都和後面的數字比較大小,時間復雜度為O(n^2),效率太低。

  利用歸並排序的思想,先將數組分解成為n個長度為1的子數組,然後進行兩兩合並同時排好順序。

  在對兩個子區域合並排序時,記左邊區域(下標為start~mid)的指針為i,右邊區域(下標為mid+1~end)的指針為j,兩個指針都指向該區域內最大的數字,排序時:

  (1)如果i指向的數字大於j指向的數字,說明:逆序對有j-mid個,我們把i指向的數字放入臨時創建的排序數組中,然後令i-1,指向該區域前一個數字,繼續進行排序;

  (2)如果i指向的數字小於等於j指向的數字,說明暫時不存在逆序對,將j指向的數字放入臨時創建的排序數組中,然後令j-1,指向該區域前一個數字,繼續進行排序;

  (3)某一子區域數字都放入排序數組後,將另一個子區域剩下的數字放入排序數組中,完成排序;

  (4)最後將排序好的數字按順序賦值給原始數組的兩個子區域,以便合並後的區域與別的區域合並。

技術分享圖片

測試算例 

  1.功能測試(普通數組,遞增數組,遞減數組,含重復數字)

  2.邊界值測試(數組只有兩個數字,只有一個數字

  2.特殊測試(null)

Java代碼、

//題目:在數組中的兩個數字如果前面一個數字大於後面的數字,則這兩個數字組
//成一個逆序對。輸入一個數組,求出這個數組中的逆序對的總數。

public class InversePairs {
    public static int inversePairs(int [] array) {
        if(array==null || array.length<=0)
            return 0;
        int count=getCount(array,0,array.length-1);
        return count;
    }
    
    private static int getCount(int[] array,int start,int end){
        if(start>=end)
            return 0;
        int mid=(end+start)>>1;
        int left=getCount(array,start,mid);
        int right=getCount(array,mid+1,end);
        
        //合並
        int count=0;
        int i=mid; //左邊區域的指針
        int j=end; //右邊區域的指針
        int[] temp= new int[end-start+1];  //臨時區域
        int k=end-start; //臨時區域的指針
        while(i>=start && j>=mid+1){
            if(array[i]>array[j]){
                count+=(j-mid);
                temp[k--]=array[i--];
            }else{
                temp[k--]=array[j--];
            }
        }
        while(i>=start)
            temp[k--]=array[i--];
        while(j>=mid+1)
            temp[k--]=array[j--];
        for(k=0;k<temp.length;k++)
            array[k+start]=temp[k];
        
        return count+left+right;
    }
}

  

收獲

  1.要對歸並排序的實現非常熟練。

  

更多:《劍指Offer》Java實現合集

  

【Java】 劍指offer(51)數組中的逆序對