1、快速排序
因为快速排序每次在排序时是将锚点元素给放到了排序后的正确位置上,因此我们可以根据锚点元素排序后的位置来确定我们应该是在他的左侧寻找还是右侧寻找,最终确定第k大的元素。
class Solution {
public:
int topK(vector<int> &nums, int left, int right, int k) {
int base, i, j;
if (left >= right) return nums[left];
base = nums[left];
i = left;
j = right;
while (i < j) {
while (nums[j] <= base && i < j) {
j--;
}
while (nums[i] >= base && i < j) {
i++;
}
if (i < j) {
swap(nums[i], nums[j]);
}
}
nums[left] = nums[i];
nums[i] = base;
if (i + 1 == k) {
return nums[i];
} else if (i + 1 < k) {
return topK(nums, i + 1, right, k);
} else {
return topK(nums, left, i - 1, k);
}
}
int findKthLargest(vector<int> &nums, int k) {
return topK(nums, 0, nums.size() - 1, k);
}
};
2、堆排序
因为我们需要寻找数组中第k大的数,所以我们可以选择维护一个大小为k的小顶堆,则堆顶就是第k大的数。
使用STL:
int findKthLargest(vector<int>& nums, int k) {
priority_queue<int, vector<int>, greater<int>> pq;
for (auto n : nums) {
if (pq.size() == k && pq.top() >= n) continue;//堆大小已经为k时直接与堆顶元素进行判断即可
if (pq.size() == k) {
pq.pop();
}
pq.push(n);
}
return pq.top();
}
自己实现小顶堆:
void adjustHeap(vector<int>& hp, int idx, function<bool(const int& a, const int& b)> cmp) {
for (int i = idx; i * 2 + 1 < hp.size();) {
int t = i * 2 + 1;
t += (t + 1 < hp.size() && !cmp(hp[t + 1], hp[t]));
if (!cmp(hp[i], hp[t])) break;
swap(hp[i], hp[t]);
i = t;
}
}
void buildHeap(vector<int>& hp, function<bool(const int& a, const int& b)> cmp) {
for (int i = hp.size() / 2 - 1; i >= 0; i--) {
adjustHeap(hp, i, cmp);
}
}
int findKthLargest(vector<int>& nums, int k) {
if (k == 0) return {};
vector<int> ans(nums.begin(), nums.begin() + k);
auto cmp = [](const int& a, const int& b) { return a > b; };
buildHeap(ans, cmp);
for (int i = k; i < nums.size(); i++) {
if (!cmp(nums[i], ans[0])) continue;
ans[0] = nums[i];
adjustHeap(ans, 0, cmp);
}
return ans[0];
}