第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 第...