給定線性序集中n個元素和乙個整數k,n<=2000000,1<=k<=n,要求找出這n個元素中第k小的數。
第一行有兩個正整數n,k.
接下來是n個整數(0<=ai<=1e9)。
輸出第k小的數
6 3
1 3 5 2 4 6
3
利用快速排序可以找出第k小的,加上隨機函式改進一下:
ac**:
#include
#include
#include
#include
int num[
2000001];
void
quictsort
(int
,int
,int);
intpartition
(int
,int);
intmain()
return0;
}// 快速排序
void
quictsort
(int left,
int right,
int mtop)
}// 從小到大排
intpartition
(int left,
int right)
num[left]
= key;
// 將隨機選擇的數存回
return left;
// 返回隨機選擇的數分割陣列的下標, 左邊都是比它小的, 右邊都是比它大的
}
中位數法線性時間選擇劃分:
}// 中位數法線性時間選擇
intselect
(int low,
int high,
int top)
int groupnum =
(high - low -4)
/5;// 每組5個數, 計算多少個組, 從0開始計數
for(
int i =
0; i <= groupnum; i++
)// 上面排完後, 陣列low + 0 到 low + groupnum都是每一組的中位數
int median =
select
(low, low + groupnum,
(groupnum +1)
/2);
// 找中位數的中位數
int p =
partition
(low, high, median)
;// 將陣列分為兩段, 左邊的小於中位數的中位數, 右邊的大於中位數的中位數
int n = p - low;
// 計算p到low之間有多少個數, 後面得減掉
if(n == top)
return num[p]
;// 如果運氣好, 剛好要找的就是中位數
if(n > top)
return
select
(low, p -
1, top)
;// n比top大就在左邊找
if(n < top)
return
select
(p +
1, high, top - n -1)
;// n比top小就在右邊找, 並且top要減去已經大的個數
}// 以中位數進行分割, 分成兩半
intpartition
(int low,
int high,
int median)
// 將中位數交換到最前面
swap
(num[p]
, num[low]);
// 記下最前面的數
int key = num[low]
;// 把小於key的放前面, 大於key的放後面
while
(low < high)
// 分別從兩頭開始, 找到中間時, 把key存回
num[low]
= key;
return low;
}// 選擇排序
void
selectsort
(int low,
int high)
}// 交換兩個元素
void
swap
(int
&a,int
&b)
分治法 線性時間選擇
演算法思想 利用快速排序的方法將a p r 被劃分成兩個子陣列a p i 和a i 1 r 使a p i 中的每個元素都不大於a i 1 r 中每個元素。接著演算法計算子陣列a p i 中元素個數j。如果k j,則第k小的數落在左區間,否則落在右區間,直到k j時,找到第k小的數。對於有重複數字的無...
分治法 線性時間選擇
問題 給定線性序集中n個元素和乙個整數k,1 k n,要求找出這n個元素中第k小的元素,演算法的複雜度為o n 思路分析 首先,假如我們要找最大或者最小的元素,那麼只需遍歷一遍序列即可,複雜度為o n 假如要找第k大的元素,k n logn或者k n nlogn時,利用堆排序,時間複雜度仍然可以達到...
分治法 線性時間選擇(求第k小數)
給定線性序集中n個元素和乙個整數k,1 k n,要求找出這n個元素中第k小的元素,這裡給定的線性集是無序的 線性時間選擇隨機劃分法可以模仿隨機化快速排序演算法設計。基本思想是對輸入陣列進行遞迴劃分,與快速排序不同的是,它只對劃分出的子陣列之一進行遞迴處理。利用隨機函式產生劃分基準,將陣列a p r ...