算法學習之數組中的逆序對

題目描述

在數組中的兩個數字,如果前面一個數字大於後面的數字,則這兩個數字組成一個逆序對。輸入一個數組,求出這個數組中的逆序對的總數P。並將P對1000000007取模的結果輸出。 即輸出P%1000000007

輸入描述:

題目保證輸入的數組中沒有的相同的數字

數據範圍:

對於%50的數據,size<=10^4

對於%75的數據,size<=10^5

對於%100的數據,size<=2*10^5

示例1

輸入

1,2,3,4,5,6,7,0

輸出

7

思路,如果我們暴力一點,可以直接嵌套雙遍歷進行獲取個數就完事了,可是這樣,每次都拿出一個數跟其他比較,複雜度太大:n^2。所以這裏使用了小套路:歸併排序。現將數組分解成單個元素,然後兩個相鄰的進行比較,如果前邊的打則符合條件,我們進行計數,並進行排序,防止下次重複計數。然後比較同一組的另外相鄰的兩個元素,同理。最後比較已兩個爲基本單位的兩個組合,進行混合比較同時計數和排序。說起來可能有點蒙,這裏爲了方便理解盜了張圖。這樣至少節省了一般以上的時間成本。

 

import java.util.*;
public class Solution {
    int count = 0;
    public int InversePairs(int [] array) {
        mergeSort(array,0,array.length-1);
        return count;
    }
    // 歸併排序開始,即遞歸形式把數組切割成單個元素,然後回馬槍開始排序同時統計count
    public void mergeSort(int [] array,int lo,int hi){
               if(lo==hi)return;
               int mid = (lo+hi)>>1;
               mergeSort(array,lo,mid);
               mergeSort(array,mid+1,hi);
               merge(array,lo,mid,hi);
    }
    public void merge(int [] array,int lo,int mid,int hi){
               // k記錄當前輔助數組索引
               // p1記錄左半段開始索引位置
               // p2記錄右半段開始索引位置
               int k = 0, p1 = lo,p2 = mid+1; 
               int [] copy = new int[hi-lo+1];
               while(p1<=mid&&p2<=hi){
                    if(array[p1]>array[p2]){ // 前邊大,說明p1處至p2處中間這些數都能與p1位置處組成逆序對
                        count=(count+(mid-p1+1))%1000000007;
                        copy[k++] = array[p2++]; // 把較小的放入到輔助數組
                    }else{
                        copy[k++] = array[p1++];
                    }
               }
               // 將剩餘的賦值到輔助數組copy中
               while(p1<=mid){
                   copy[k++] = array[p1++];
               }
               while(p2<=hi){
                   copy[k++] = array[p2++];
               }
               // 把輔助數組的值賦給相應位置的原數組,開始下次merge
               for(int i = 0;i < k;i++){
                   array[i+lo] = copy[i];
               }
    }
}
  • 時間複雜度:O(nlogn)。
  • 空間複雜度:O(n)。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章