歸併 逆序數 快排 第k小數

2021-10-25 02:14:14 字數 1579 閱讀 1362

目錄

歸併排序:

完整**:

快速排序:

思路:進行二分,然後合併。對於合併的兩個模組,每乙個模組必定已排好,因為是排完才合併。

例如2 4 6 | 1 3 7;雙「指標」,乙個指向左邊、乙個指向右邊。

右邊1《左邊2  1進入b陣列 此時2 4 6|3 7  b=;

右邊3>左邊2  2進入b陣列 此時4 6|3 7    b=

……以此類推。

由此發現,右邊的進入時,左邊剩下了多少就有多少逆序對,並且合併回溯過程中,每乙個數都會和它前面的數進行分組(就是這裡的左右)。

所以,只需在需要將右邊數加入時加上這條語句即可ans += (ll)(mid-p1+1);mid時最後乙個左組元素的下標。

注意:等號的時候讓左組進入,因為相等這不是逆序對。

void _merge(int l,int mid,int r)//等號無所謂,這裡為了求逆對數,相等的情況讓前面的先進去,主要靠後面進行求逆對數 

else

} for(int i = l;i <= r;i++) a[i] = b[i];

return ;

}void erfen(int l,int r)

_merge(l,mid,r);

return ;

}

#include#include#include#include#include#include#include#includeusing namespace std;

typedef long long ll;

const int maxn = 1e6+50;

ll a[maxn];

ll b[maxn];

ll ans;

void _merge(int l,int mid,int r)//等號無所謂,這裡為了求逆對數,相等的情況讓前面的先進去,主要靠後面進行求逆對數

else

} for(int i = l;i <= r;i++) a[i] = b[i];

return ;

}void erfen(int l,int r)

_merge(l,mid,r);

return ;

} int main()

找到乙個基準點,小於它的在左側,大於它的在右側,然後遞迴對兩側同樣執行。

void q_sort(int l,int r)

} if(l < j)

q_sort(l,j);

if(i < r)

q_sort(i,r);

}

尋找第k小數,那麼就進行改進。

如果找到了乙個數,基準點位置最後在….x…..,如果xk的話,右側肯定不會是第k小數,因為左側多餘k個數,右側都大於左側,所以肯定在左側。

void q_sort(int l,int r)

}if(k == i-1)

else if(k < i-1)

else q_sort(i,r);

}

快排求逆序數 快排與歸併時間複雜度比較

本文參考其他用快排求逆序數的方法。在用快排求解逆序數前,我先考慮了這個問題,1 歸併和快排的時間複雜度都是nlog n 為什麼不用歸併?我認為應該是由於快排在每次合併時都有用到臨時陣列,然後每次還需要把臨時陣列重新copy到原陣列中 增加了時間複雜度 快排雖然也存在最壞的情況,即n 2,但是由於其隨...

基於快排求無序陣列的第K大元素

package other pratice 怎麼最快的求無序陣列的第k大元素。author sxy 我們知道快排的排序是從大到小,還是從小到大取決於分割槽那個函式是如何寫的,本題是在陣列中尋找第幾大元素 所以需要在陣列的大小的順序要是從大到小 快速排序每次排序完找的 基準點即是第幾大元素。如果 如果...

快速排序 快排求第K大

快速排序 快排採用分治的策略,先從數列中取出乙個元素作為作為基準元素,以基準元素為標準,將問題分解為兩個子串行,使小於基準的子串行在左側,使大於等於基準元素的子串行右側,對兩個子串行再進行快速排序,最終得到排好序的序列。時間複雜度 o nlogn 空間複雜度o logn 快速排序是不穩定的 code...