1. 程式人生 > >求第k小數(分治)

求第k小數(分治)

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;
}

實際上我是用快排排了序然後直接查詢的……