逆序對《演算法很美》

kongbai發表於2020-12-18

逆序對

不懂歸併的可以,看我之前的文章
思路: 歸併排序的基礎上,加上static int niXu = 0;
記住遞迴是歸併,兩兩歸併,兩兩比對的,是拆分了的。niXu是內部進行比對相加的。

具體思路:

  1. {9,9,6,7,5,4,2,2,1}
  2. 9和{5,4,2,2,1} 9大於5、4、2、2、1 niXu = 5;
  3. 9和{5,4,2,2,1} 9大於5、4、2、2、1 niXu = 5;
  4. 6和{5,4,2,2,1} 6大於5、4、2、2、1 niXu = 5;
  5. 7和{5,4,2,2,1} 7大於5、4、2、2、1 niXu = 5;
  6. 5和{4,2,2,1} 5大於4、2、2、1 niXu = 4;
  7. 4和{2,2,1} 4大於2、2、1 niXu = 3;
  8. 2和{2,1} 2大於2、1 niXu = 2;
  9. 2和{1} 2大於1 niXu = 1;
public class 逆序對 {

    public static int[] helper;
    static int niXu = 0;


    public static void sort(int[] arr){
        helper = new int[arr.length];
        sort(arr, 0, arr.length - 1);
    }

    public static void sort(int[] A,int p,int r){
        if(p < r){
            int mid = p+((r-p)>>1);
            sort(A, p, mid); //對左側排序
            sort(A,mid+1, r);  //對右側排序
            merge(A, p, mid, r);  //合併
        }
    }


    public static void merge(int[] A,int p,int mid,int r){

        //拷貝到輔助空間的相同位置
        System.arraycopy(A, p, helper, p, r - p + 1);
        //輔助陣列的兩個指標
        int left = p;
        int right = mid + 1;
        //原始陣列的指標
        int current = p;

        while(left <= mid && right <= r){
            if(helper[left] <= helper[right]){
                A[current++] = helper[left++];
            }else{ //右邊小
                A[current++] = helper[right++];
                niXu=niXu+mid-left+1;
            }
        }

        // 這樣做完後,左邊指標可能沒到頭;右邊的沒到頭也沒關係,想想為什麼?
        while (left <= mid) {
            A[current] = helper[left];
            current++;
            left++;
        }
    }

    public static void main(String[] args){
        int[] arr = {9,9,6,7,5,4,2,2,1};
        Util.print(arr);
        sort(arr);
        System.out.println();
        Util.print(arr);
        System.out.println();
        System.out.println("niXu:" + niXu);


    }
}

相關文章