求逆序數的分治演算法

2021-05-22 06:26:53 字數 826 閱讀 3051

給我們乙個序列, 讓我們求其逆序數:

如3 2 1 4

逆序數為: 2+1+0+0=3

我們這樣定義乙個序列的逆序數: 序列a1 a2 a3 a2 ...an

這個序列的逆序數c, 等於a1,a2...的逆序數的和.即 c=sum(ci)

ci為滿足ai > aj (j > i)的數的總的個數, 即ci = sum(ai > aj) (j >i).

我們一般寫的演算法一般會做n(n-1)/2次比較, 時間複雜度為: o(n^2).

下面採用的分而治之的思想來改進:

假設我們將序列a1 a2 a3 a2 ...an分成兩份: b0=(a1 a2 an/2) b1 = (a (n/2+1)...an)

那麼c=c(b0)+c(b1)+m(b0b1)

如果我們直接去計算m(b0b1), f(n) = 2*f(n/2)+c*n^2, 計算出來的結果是f(n)=n*f(1) + 2c*n^2 - 2c*n, 那麼效率依然是o(n^2), 我們通過什麼方式改進呢?

那假如讓b0,b1有序就好了! 嗯,對的. 我們在歸併排序的過程先將b0,b1排成有序數列,再來求b0′b1′的逆序數, 這時求m(b0′b1′)效率就是o(n).

即,c=c(b0′) + c(b1′) + m(b0′b1′).

下面給出求c(b0′b1′)的**, 你在下面的完整的求逆序數的演算法中也可以找到:

這時f(n) = 2*f(n/2)+c*n, 我計算出來的結果是f(n) = n*f(1) + c*n*log(n)

時間複雜度o(n*logn)和空間複雜度o(n)都和歸併演算法一致, 只比比歸併演算法大了乙個常數因子.

歡迎拋磚.

分治 求 逆序數

利用歸併,逆序數等於 左邊逆序數 右邊逆序數,加上 左邊 的每個數與右邊的每個數構成的逆序數。歸併過程 把 左邊和右邊按照從小到大排序 在 merge過程中發現a 右邊 a 左邊 說明 在此左邊p1位置的右側的數都能與 此時的p2位置的 a p2 構成逆序對。故 逐一對a j 進行判斷,累加即可得到...

分治遞迴逆序數 逆序數的分治演算法

給我們乙個序列,讓我們求其逆序數 如3 2 1 4 逆序數為 2 1 0 0 3 我們這樣定義乙個序列的逆序數 序列a1 a2 a3 a2 an 這個序列的逆序數c,等於a1,a2.的逆序數的和.即 c sum ci ci為滿足ai aj j i 的數的總的個數,即ci sum ai aj j i ...

分治求逆序數(CDQ)

歸併排序 includeusing namespace std int b 100 void merge sort int l,int r,int a else for int i l i r i a i b i int main merge sort 0,9,c for int i 0 i 10 ...