計算數組中的逆序數(inversion)個數


  今天繼續學了算法,首先是一個計算數組中的逆序數的算法。

  通常,很容易想到的計算辦法就是運用兩個for循環遍歷比較整個數組,當某個數字的下標較大,而值卻小於小標比它小的某個位置上的值時,逆序數+1,但是此種算法復雜度較高,隨着輸入數據規模的增大效率會快速下降(即輸入的數組變大了),具體的復雜度計算方法如下:設數組有n個元素,則需要遍歷n次,而每一次遍歷中要與下標在后面的進行比較,在當次遍歷中,其后具有(n-當次遍歷的元素的下標)個元素,那么就需要進行n^2/2次操作(后面的元素不需要再與前面的比較),運用notation,最后復雜度應該表示為O(n^2),所依此算法的效率就隨n的增大而快速降低。所以呢?我們提出一個問題:Can we do better?

  Of course we can, there is always another way.怎么解決呢?其中一個方法是用merge算法。(具體是什么自行研究吧我也還在學習中,簡單的說就是把數組分成相等的兩部分,如果是奇數就一邊多了一個,另一半少一個,然后就不斷遞歸,分別把兩部分等分成更小的相等部分,最后分到一定小后排好序,分別找出兩部分中分別含有的逆序數(兩個數都在一個部分中),還有就是“構成逆序數”的兩個數字分別在兩部分中),接下來的重點就是找出第二種“逆序數”(我的意思是構成逆序數的第二種方式,就是兩個數在不同的兩個部分),而merge算法解決這個就很有優勢,理由如下:比如員數組是[ 1, 3, 5, 2, 4, 6],分成兩部分后排好序分別為A[1 , 3, 5], B[ 2, 4, 6],最終的輸出結果為D[1, 2, 3, 4, 5, 6],那么作如下圖:(相同數字上下連線,連線交點數即為結果)

1  3  5 , 2   4   6

1  2  3     4   5   6

為什么呢?由A,B生成D的過程就是merge過程,merge通過

i=0, j = 0;

for k=0 to n:

  if A[i] < B[j]:

    D[k] = A[i];

    i++;

  else if A[i] > B[j]:

    D[k] = B[j];

    j++;

這個過程生成最后的D,由此很容易看出,如果在A未被完全轉移到D之前,B中的某個元素先被移到了D中,那么當B中這個元素移動時,A中還剩余有多少個元素未移到D的,A中就有多少個元素比這個B中的元素大。綜上,交點數即“那種逆序數”。


免責聲明!

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



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