歸併排序以及逆序對問題

2022-07-10 21:39:11 字數 1536 閱讀 7568

void merge_sort(int q, int l, int r)

, k = 0, i = l, j = mid+1;

while(i<=mid && j<=r)

while(i<=mid) tmp[k++] = q[i++];

while(j<=r) tmp[k++] = q[j++];

for(int i = l, j = 0; i<=r; i++,j++) q[i] = tmp[j];

}

歸併排序與快速排序的分治合差別:

歸併是從下往上進行出遞迴的時候進行資料的處理,要進行合併。

快速排序是從上往下的時候進行分治,不用進行合併。

習題:788.逆序對的數量

給定乙個長度為n的整數數列,請你計算數列中的逆序對的數量。

逆序對的定義如下:對於數列的第 i 個和第 j 個元素,如果滿足 i < j 且 a[i] > a[j],則其為乙個逆序對;否則不是。

輸入格式

第一行包含整數n,表示數列的長度。

第二行包含 n 個整數,表示整個數列。

輸出格式

輸出乙個整數,表示逆序對的個數。

int res;

void merge_sort(int q, int l, int r), k = 0 ,i = l, j = mid+1;

while(i <= mid&& j<=r)

}while(i <= mid) tmp[k++] = q[i++];

while(j <= r) tmp[k++] = q[j++];

for(int i = l, j = 0; i <= r; i++,j++) q[i] = tmp[j];

}

為什麼只在歸併排序的基礎上增加了:

res+=mid-i+1;
就能解出這道題?

假設在最後一次排列中的資料為

2 3 4 || 1 5 6
mid = 4 ; i =2; j = 5;首先,兩部分資料在上一層遞迴中已經得到了排序,所以兩部分資料均為有序狀態。因此,上一層遞迴的逆序對已經算出。我們只需要將res加上本層遞迴所算出來的逆序對個數即可。

可以很明顯的看出,要先放置1temp中,放了1之後,從i~mid都會比1大,因為程式中經過了此次對比

if(q[i] > q[j]) tmp[k++] = q[j++];
在左右兩邊均為有序的狀態下,左邊會有i - mid+1個數比此時的q[j]大,所以要用res+=i-mid+1.

逆序對 (歸併排序)

逆序對的nlogn方法,改進後的歸併排序 給定排列p,求排列的逆序對數量。p的長度 100000。要求o nlogn 定義歸併排序過程merge l,r merge l,r merge l,mid merge mid 1,r count l,mid,mid 1,r 只需要考慮左右兩段之間造成的逆序對...

歸併排序 逆序對

按照劉汝佳說的,歸併排序分三步 1.劃分問題,即把序列分成元素盡量相等的兩半 2.遞迴求解 3.合併子問題 其實就是把乙個序列不斷的二分,直到只有兩個元素的時候,然後排序,然後返回,再排序。先上 include using namespace std long long a 100005 t 100...

歸併排序(逆序對)

現在我們在競賽中最常用的排序是快速排序,c 只要乙個sort就搞定,但非常明顯,歸併排序的時間複雜度是最優的而且非常穩定,但是人們經常把它用在求逆序對個數上面。那麼下面我用乙個這樣的題來講一下歸併排序。點這裡看題目和樹狀陣列解法。歸併排序是將數列a l,h 分成兩半a l,mid 和a mid 1,...