給我們乙個序列, 讓我們求其逆序數:
如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 從行列式開始 如果忘記呢,問題也不大,這個概念比較簡單,我想大家很快就能都搞清楚。...