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

2021-10-16 20:35:01 字數 2085 閱讀 6072

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

如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′)的**, 你在下面的完整的求逆序數的演算法中也可以找到:

inti = x, j = m;//序列b0[x,y], b1[m, n]

for(i = x; i <= y; ++i)

while(j <= n && arr[i] > arr[j])

++j;

norder += j-m;

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

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

歡迎拋磚.

#include

#include

usingnamespacestd;

voidswap(int*arr,inti,intj)

inttmp = arr[i];

arr[i] = arr[j];

arr[j] = tmp;

intmerge(int* temp,int*arr,intx,inty,intm,intn)

intnorder = 0;

inti = x, j = m;

for(i = x; i <= y; ++i)

while(j <= n && arr[i] > arr[j])

++j;

norder += j-m;

intk = 0;

i = x, j = m;

while(i <= y && j <= n)

if(arr[i] <= arr[j])

temp[k++] = arr[i++];

else

temp[k++] = arr[j++];

while(i <= y)

temp[k++] = arr[i++];

while(j <= n)

temp[k++] = arr[j++];

returnnorder;

intinversion_number(int*arr,inti,intj)

if(i 

intmid = i+((j-i)>>1);

intv1 = inversion_number(arr, i, mid);

intv2 = inversion_number(arr, mid+1, j);

inttemp[10];

intnvalue = merge(temp, arr, i, mid, mid+1, j);

memcpy(arr+i, temp, sizeof(int)*(j-i+1));

returnv1+v2+nvalue;

else

return0;

intmain()

intarr = ;

cout <

return0;

分治遞迴逆序數 模板 歸併排序 逆序數 分治

歸併排序 圖來自維基 遞迴呼叫的過程需要在腦中模擬清楚 然後是 的細節問題 多複習多理解 劉汝佳版 include using namespace std const int maxn 1e5 10 int ans 0 int arr maxn int brr maxn void mergesort...

分治 求 逆序數

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

分治遞迴逆序數 歸併演算法經典應用 求解逆序數

原創不易,求個關注 在之前介紹線性代數行列式計算公式的時候,我們曾經介紹過逆序數 我們在列舉出行列式的每一項之後,需要通過逆序數來確定這一項符號的正負性。如果有忘記的同學可以回到之前的文章當中複習一下 線性代數精華1 從行列式開始 如果忘記呢,問題也不大,這個概念比較簡單,我想大家很快就能都搞清楚。...