问题描述:
给定一个整形数组array, 一个整型值k,寻找数组array中第k大的数,假定k值总有效,即0<=k<=array.length -1
算法 SELECT
输入: n个元素的数组A[1…n]和整数k, 1<=k<=n。
输出:A中的第K大元素。
1、 select(A, 1, n, k)
过程 select(A, low, high, k)
1. p = high - low + 1
2. if p < 44 then 将A排序return (A[k])
3. 令 q =⌊p/5⌋。将A分成q组,每组5个元素。如果5不整除p,则派出剩余的元素。
4. 将q组中的每一组单独排序,找出中项。所有中项的集合为M。
5. mm = select(M, 1, q, ⌈q/2⌉) {mm为中项集合的中项}
6. 将 A[low…high]分成3组
A1 = {a | a > mm}
A2 = {a | a = mm}
A3 = {a | a < mm}
7. case
|A1| ≥ k: return select(A1, 1, |A1|, k)
|A1| + |A2| ≥ k: return mm
|A1| + |A2| < k: return select(A3, 1, |A3|, k - |A1| - |A2|)
8. end case
其中阈值为44的原因这里不再讲解
以下是C++代码,为AC状态。
class Solution {
public:
int findKthLargest(vector<int>& nums, int k) {
vector<int>::size_type totalCount = nums.size();
if (totalCount < 44) {
sort(nums.begin(), nums.end(), greater<int>());
return nums[k - 1];
}
vector<int>::size_type groups = totalCount / 5;
vector<int> mediums;
for (vector<int>::size_type gix = 0; gix < groups; gix++) {
sort(nums.begin() + 5 * gix, nums.begin() + 5 * (gix + 1), greater<int>());
mediums.push_back(*(nums.begin() + 5 * gix + 2));
}
int mm = findKthLargest(mediums, ceil(groups / 2.0));
vector<int> nums1, nums2, nums3;
for (vector<int>::size_type ix = 0; ix != nums.size(); ix++) {
if (nums[ix] > mm) {
nums1.push_back(nums[ix]);
}
else if (nums[ix] < mm) {
nums3.push_back(nums[ix]);
}
else {
nums2.push_back(nums[ix]);
}
}
if (nums1.size() >= k) {
return findKthLargest(nums1, k);
}
else if (nums1.size() + nums2.size() >= k) {
return mm;
}
else {
return findKthLargest(nums3, k - nums1.size() - nums2.size());
}
}
};