题意:求一个数组中第k大的元素
https://leetcode.com/problems/kth-largest-element-in-an-array/description/
题解:
可以用heap或者快选
heap解法:
heap中保存的应该是前k大的元素,前k大的元素我可以用一个最小堆维护,如果堆中元素个数小于k,或者当前扫描的数字大于堆顶我就放进堆中。扫描结束后,堆顶的元素就是答案
class Solution {
public:
int findKthLargest(vector<int>& nums, int k) {
priority_queue<int, vector<int>, greater<>> q;
for(int i = 0; i < nums.size(); i++) {
if( q.size() < k ) {
q.push(nums[i]);
continue;
}
if(nums[i] > q.top()) {
q.pop();
q.push(nums[i]);
}
}
return q.top();
}
};
算法复杂度:
O
(
N
l
o
g
k
)
O(Nlogk)
O(Nlogk)
空间复杂度
O
(
1
)
O(1)
O(1)
快速选择解法:先找到一个pivot,左右两边需要满足pviot左边的值都比pivot小,右边的值都比pivot大
为l和r的中点元素,并且有i,j两个指针从数组两端开始,一旦有指针i指向的元素大于pivot就停下,指针i指向的元素小于pivot就停下,此时表明
不断交换i和j的元素,直到 i > j, 那么在这次的iteration中, [l, j], [j, i][i,r]分成了三个区间,j,i之间只有一个元素
class Solution {
public:
int findKthLargest(vector<int>& a, int k) {
int n = a.size();
k = n-k;
return qs(a, 0, n - 1, k);
}
int qs(vector<int>& a, int l, int r, int k) {
while( l < r ) {
int piv = a[l + (r - l) / 2];
int i = l;
int j = r;
while (i <= j) {
while(a[i] < piv) i++;
while(a[j] > piv) j--;
if(i <= j) swap(a[i++], a[j--]);
}
if(k <= j) {
r = j;
} else if (k >= i) {
l = i;
} else {
break;
}
}
return a[k];
}
};
时间复杂度:
O
(
n
)
O(n)
O(n)
空间复杂度:
O
(
1
)
O(1)
O(1)