求第k小數(分治)
阿新 • • 發佈:2018-12-11
1574.求第k小數
時限:1000ms 記憶體限制:10000K 總時限:3000ms
描述
求第k小數
輸入
先輸入一個小於10000的正整數n,再輸入n個整數,最後輸入一個小於等於n的正整數k,
輸出
輸出其中第k小的數。
輸入樣例
5 2 98 34512 8492 1000 2
輸出樣例
98
#include <stdio.h> #include <algorithm> #include <math.h> using namespace std; //劃分——每次劃分唯一確定一個元素位置 int partition(int A[], int low, int high) { int pivot = A[low]; //一般採用嚴蔚敏教材版本,以第1個位置為基準 while (low < high){ while (low < high && A[high] >= pivot){ --high; } A[low] = A[high]; //將比基準小的元素移動到左端 while (low < high && A[low] <= pivot){ ++low; } A[high] = A[low]; //將比基準小的元素移動到右端 } A[low] = pivot; return low; } int r = 5; //A[low..high] int select_rank_k(int A[], int low, int high, int k) { int r_group = ceil((high - low + 1)*1.0 / r);//ceil取上限,總共分為r_group個組 //計算每個分組中值,存於A[]最前面 for (int i = 1; i <= r_group; ++i) { sort(&A[low + (i - 1)*r], &A[(low + i*r - 1) > high ? high : (low + i*r - 1)]); swap(A[low + i - 1], A[low + (i-1)*r + r / 2]); } //獲得每個組的中值的中值(並置於A[low]位置,方便呼叫快排劃分函式) sort(&A[low], &A[low + r_group]); swap(A[low], A[low + r_group / 2]); int cur = partition(A, low, high); if (cur == k-1){ return A[cur]; } else if (cur < k){ return select_rank_k(A, cur + 1, high, k); } else{ return select_rank_k(A, low, cur - 1, k); } } int main(void) { int A[15] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 }; printf("%d\n", select_rank_k(A, 0, 3, 2)); return 0; }
實際上我是用快排排了序然後直接查詢的……