在數組中的兩個數字,若是前面一個數字大於後面的數字,則這兩個數字組成一個逆序對。輸入一個數組,求出這個數組中的逆序對的總數:算法
如數組{7,5,6,4},逆序對總共有5對,{7,5},{7,6},{7,4},{5,4},{6,4};數組
思路1:暴力解法,順序掃描整個數組,每掃描到一個數字的時候,逐個比較該數字和它後面的數字的大小。若是後面的數字比它小,則這兩個數字就組成一個逆序對。假設數組中含有n個數字,因爲每一個數字都要和O(n)個數字做比較,所以這個算法的時間複雜度是O(n2)。spa
思路2:分治思想,採用歸併排序的思路來處理,以下圖,先分後治:code
先把數組分解成兩個長度爲2的子數組,再把這兩個子數組分解成兩個長度爲1的子數組。接下來一邊合併相鄰的子數組,一邊統計逆序對的數目。在第一對長度爲1的子數組{7}、{5}中7>5,所以(7,5)組成一個逆序對。一樣在第二對長度爲1的子數組{6},{4}中也有逆序對(6,4),因爲已經統計了這兩對子數組內部的逆序對,所以須要把這兩對子數組進行排序,避免在以後的統計過程當中重複統計。blog
逆序對的總數=左邊數組中的逆序對的數量+右邊數組中逆序對的數量+左右結合成新的順序數組時中出現的逆序對的數量;排序
總結統計數組逆序對的過程:先把數組分隔成子數組,先統計出子數組內部的逆序對的數目,而後再統計出兩個相鄰子數組之間的逆序對的數目。在統計逆序對的過程當中,還須要對數組進行排序,其實這個排序過程就是歸併排序的思路。class
代碼實現思路以下:im
//數組中的逆序對 public static int InversePairs(int[] array){ if(array==null||array.length<=1) return 0; int[] copy = new int[array.length]; for(int i=0;i<array.length;i++){ copy[i] = array[i]; } return mergeCount(array, copy, 0, array.length-1); } public static int mergeCount(int[] array, int[] copy, int start, int end){ if(start==end){ copy[start] = array[start]; return 0; } int mid = (start+end)>>1; int leftCount = mergeCount(copy, array, start, mid); int rightCount = mergeCount(copy, array, mid+1, end); int i = mid;//i初始化爲前半段最後一個數字的下標 int j = end;//j初始化爲後半段最後一個數字的下標 int index = end;//輔助數組複製的數組的最後一個數字的下標 int count = 0;//計數--逆序對的數目 while(i>=start&&j>=mid+1){ if(array[i]>array[j]){ copy[index--] = array[i--]; count += j-mid; }else{ copy[index--] = array[j--]; } } for(;i>=start;i--){ copy[index--] = array[i]; } for(;j>=mid+1;j--){ copy[index--] = array[j]; } return leftCount+rightCount+count; }