樹狀陣列求逆序對 演算法系列之 陣列中的逆序對

2021-10-11 16:09:35 字數 1976 閱讀 8992

題目** 劍指offer

01 題目描述在陣列中如果前乙個數字大於後乙個數字,則稱為這個數字組合組成乙個逆序對。輸入乙個陣列,求所有的逆序對的總數。

如 陣列 則它的逆序對是 (7,5),(7,6),(7,4),(5,4) ,(6,4)總共有五個。

02 解法1

類似的題目,我們的第一反應都是,固定乙個數,如7,然後從後面的數5,6,4中尋找是否有小於7的數,組成逆序對。這種方式實現的時間複雜度是 o(n^2)。

03 解法2

我們在學習演算法的時候,學習過歸併排序。如 7,5,6,4。先將陣列拆分,然後再合併。合併的過程中對比排序。

初始化reversecount = 0;

如下圖將陣列拆分

合併 7,5 6,4

我們發現 (7,5) , (6,4)可以組成乙個逆序對, reversecount+=2;

繼續下面的合併,分析 左邊=5,7 右邊= 4,6

因為在這次合併的時候,組內已經是有序的了,所以組內右邊是最大值。

對比7比,右邊=4,6 的最大值6都大。所以此時我們可以計算reversecount+=2(右面數值長度);將7放入合併陣列。

然後判斷5和6。此時6更大,將6放入合併陣列。

對比 5和4,5比4大,所以可以構成逆序對, reversecount+=1(右面剩餘未合併的陣列長度);

最後結束 輸出reversecount;

時間複雜度 nlog(n)

04 總結&**

1.用歸併排序實現

2.在歸併的過程中,從大到小歸併,同時判斷左邊陣列和右邊陣列的逆序對,如果左邊的值大於右邊的值,則逆序對 += 剩餘待合併的右邊的值。

public static long reversecount(int arrays)  int copyarray = new int[arrays.length]; return mergesort(arrays, copyarray, 0, arrays.length - 1);}public static int mergesort(int arrays, int copyarray, int start, int end)  int mid = (start + end) >> 1; int leftcount = mergesort(arrays, copyarray, start, mid); int rightcount = mergesort(arrays, copyarray, mid + 1, end); int count = merge(arrays, copyarray, start, end, mid); return (leftcount + rightcount + count) % (1000000007);}public static int merge(int arrays, int copyarray, int start, int end, int mid)  else  } while (i >= start)  while (j >= mid + 1)  while (start <= end)  return count;}

樹狀陣列求逆序對

題目描述 給定乙個陣列a,它包含n個整數,分別是a 1 a 2 a n 如果存在下標i和j,使得 i j 且 a i a j 同時成立,則 i,j 就為乙個 逆序對 那麼a陣列總共有多少對不同的 逆序對 輸入格式 1247.in 第一行為n 1 n 100000 接下來是n行,每行乙個長整型範圍內的...

樹狀陣列求逆序對

很久以前就學了樹狀陣列,也知道可以用來求逆序對,然而一直沒弄明白他是怎麼實現的 可能當時沒搞清楚逆序對是什麼吧。逆序對就是如果i j a i a j 這兩個就算一對逆序對,簡單來說,所有逆序對的個數和就是找每乙個數的前面有幾個比他的大的數,他們加起來的和就是逆序對的總數。知道什麼是逆序對後就好辦了,...

樹狀陣列 求逆序對

樹狀陣列可以解決線段樹能夠解決的問題,且更加節省空間。線段樹的講解 可以看這位大佬的部落格 樹狀陣列的講解 另一位大佬的部落格 這裡主要寫一下利用樹狀陣列來求解逆序對的個數。簡單來說就是一段序列裡面每個數所在位置之前的位置上比這個數大的數字個數之和。例如 1 2 3 5 4 只有 4 前面的 有乙個...