排序3 快速排序 第K大數

2021-10-21 06:40:50 字數 1850 閱讀 7997

第k大數的問題

就是求解乙個序列中第k大的數

常見做法:將原序列排序,然後訪問第n - k個數即可,總體時間複雜度o(nlogn)

而本題其實只需要求第k大數,而對於其餘的數是否有序,我們並不關心,

先回顧一下快速排序的演算法思想:

1. 在原序列中隨機找乙個中心值pivot,將小於中心值的元素放在其左邊,大於中心值的元素放在其右邊

一次快排,中心值位置就唯一確定了

2.對左右兩邊進行同樣的操作

#include#include#include//rand()

#include//swap()

using namespace std;

const int maxn = 1000 + 10;

int arr[maxn];

int partition(int left, int right)

swap(arr[left],arr[right]);

while(left < right && arr[left] <= arr[right])

swap(arr[left],arr[right]);

}return left;//此時 left == right

}void quicksort(int left,int right)

}int main()

quicksort(0, n - 1);

for(int i = 0; i < n; ++i)

return 0;

}

如何利用快速排序高效地求得第k大數呢?

在快排過程中,每一步都會將隨機選擇出來的中心值的位置唯一確定

第k大數就是原始序列在有序(從小到大)的情況下的下標index = n - k 的數

所以在快排過程中,你確定的中心值的下標正好是 n - k ,那麼這個中心值正是第k大數

而如何一步步篩選得到最終結果呢?

若此時中心值下標 < n - k,而由於快排的特性,左邊都比中心值小,右邊都比中心值大,

那麼第k大數就一定在此時的中心值的右邊,那麼下一次的隨機取值,就從右邊取了!這樣可以縮小搜尋空間

時間複雜度為 n + n/2 + n/4 +......+1 = o(n) < o(nlogn)

#include#include#include//rand()

#include//swap()

using namespace std;

const int maxn = 1000 + 10;

int arr[maxn];

int partition(int left, int right)

swap(arr[left],arr[right]);

while(left < right && arr[left] <= arr[right])

swap(arr[left],arr[right]);

}return left;//此時 left == right

}int quicksort(int left,int right,int p)else if ( position > p)else

}int main()

int answer = quicksort(0, n - 1, n - k);

printf("%d\n",answer);

return 0;

}

主要修改了quicksort函式的**,p是目標位置。

第K個數 快速排序

題目描述 description 給定乙個長度為n 0輸入描述 input description 第一行為2個數n,k 含義如上題 第二行為n個數,表示這個序列 輸出描述 output description 如果m為質數則 第一行為 yes 沒有引號 第二行為這個數m 否則 第一行為 no 第二...

快速排序區間K大數查詢

題目 問題描述 給定乙個序列,每次詢問序列中第l個數到第r個數中第k大的數是哪個。輸入格式 第一行包含乙個數n,表示序列長度。第二行包含n個正整數,表示給定的序列。第三個包含乙個正整數m,表示詢問個數。接下來m行,每行三個數l,r,k,表示詢問序列從左往右第l個數到第r個數中,從大往小第k大的數是哪...

快速排序 第K大 第K小的問題

這裡的快排 是一種稍微改進的快排,即減少一些不必要的交換次數。quick sort void quick sort int s,int e a s a i 此時 i j 為最後找到的最小的數,需要放在樞軸處 即位置s a i x quick sort s,i 1 quick sort i 1,e 第...