經典問題與演算法思想
1.計數排序
1.先輸入0~9之間的數放入陣列a中。
數字:5 3 2 4 3 3 2 7 7 1
2.建立和a一樣大小的陣列b,使用b來統計a中各個數字出現的次數。
次數:0 1 2 3 1 1 0 2 0 0
數字:0 1 2 3 4 5 6 7 8 9
3.下面陣列b的下標就對應數字,裡面的內容就是次數。如
b[4]=1,就是陣列a中數字4出現1次。
4.所以如果要輸出前 x 大的數,就逆序從b[9]開始,因為b[9]=0,棄之,直到b[7]=2,滿足出現條件,開始給陣列a從a[0]賦值,又b[7]=2出現兩次,繼續給a[1]賦值。至此,陣列a變得有序。
int a[maxn]
;int b[maxn]
;int
main()
int index =0;
//用於下標
for(
int i=
0;i++i)
//for(int i = n-1;i>=n-m;--i)輸出陣列a前n-m個數,省略
}}
對於計數排序的自定義型別如何排序,如果需要,詳見:
2.歸併排序
int arr[
100]
;int temp[
100]
;//int number;
void
combin
(int left,
int middle,
int right)
else
}while
(i<=middle)
while
(j<=middle)
for(k = left;k <= right;
++k)
return;}
void
mergesort
(int left,
int right)
}
那跟逆序對有何關係呢?
如:
此時,i 對應的數比 j 對應的數大,已經構成一組逆序對,那 j 後面的自然與 i 構成逆序對,並且 i 後面的數也與 j 後面的數構成逆序對。前面有middle-i+1個。
所以在歸併排序中,插一步,就能知道逆序對數,而不影響歸併複雜度logn * n。
所以一共有1+1+1+1+4+3=11對逆序。
3.快排
根據快排的特性:每次排序後,確定point的最終位置。
如果要找第二小的數,第一次選point=4,進行一次快排,劃分為兩部分,那麼4在arr[3],而不是在arr[1],所以不是要找的數,繼續找,那麼只需要在前一部分找即可。
//部分**進行調整
intquicksort
(int left,
int right,
int k)
else
if(positon < k -1)
else
}
逆序對 (歸併排序)
逆序對的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,...