快速排除(最優法,不是快排)求隨機陣列中第k大數(c++)(讓數隨機沒寫)
#include <iostream> using namespace std; int get_kth(int arr[], int n, int k) {
int left = 0; int right = n - 1;
while (left < right) {
while (arr[right] > arr[0] && left < right) {
right--;
}
while (arr[left] <= arr[0] && left < right) {
left++;
}
/**
* 兩個小while結束後會有left < right 仍然成立
* 所以還會繼續進行大的迴圈
* 然而,left已經達到我們想要的目的了
* 所以while(···) right--;一定要寫在前替left"擋槍"
* 在又一次經歷了遞減後@right ==
*/ cout << "前: left = " << left << " right = " << right << " | "; for (int i = 0; i < n; ++i) { cout << arr[i] << " "; } cout << endl; swap(arr[left], arr[right]); cout << "後: left = " << left << " right = " << right << " | "; for (int i = 0; i < n; ++i) { cout << arr[i] << " "; } cout << endl; } swap(arr[0], arr[left]); for (int i = 0; i < n; ++i) { cout << arr[i] << " "; } cout << endl; //此時有left個小於a[0]的且全都排在a[0]前面 //有n - right 個大於a[0]的,切全都排在最後面(a[0]後面) /** * 下面的遞迴與right沒有任何關係, * 所以只需要保證left"安全"即可 */ int _k = left + 1;//檢索到小於目標(這裡是a[0])的數量 if (_k == k) { return arr[left];//之前的a[0] } else if(_k < k) { return get_kth(arr + _k, n - _k, k - _k); }else if (_k > k){ return get_kth(arr, left, k); } }
int main() { int a[] = {2, 1, 4, 6, 3, 5, 0}; int b[] = {1, 2, 3, 4, 5, 6, 7}; int c[] = {4, 1, 3, 7, 2, 5, 6}; int d[] = {9, 1, 2, 10, 13, 5, 11}; cout << get_kth(d, 7, 6) << endl; }