题目描述
Find the kth largest element in an unsorted array. Note that it is the kth largest element in the sorted order, not the kth distinct element.
For example,
Given [3,2,1,5,6,4] and k = 2, return 5.
Note:
You may assume k is always valid, 1 ≤ k ≤ array’s length.
题意理解
找出第k大的数
分治法
算法描述
1.选出数组中的任意一个数v,将比v小,比v大,等于v的数分别放smaller,larger,equal三个数组
2.判断:
- 如果 k<=|larger| , 则说明第k大的数落在larger数组里面,递归找larger数组里面的第k大的数
- 如果 |larger|<k<=|larger|+|equal| ,则说明第k大的数落在equal数组里面,即主元素v就是要找的数,直接返回v
- 如果 |larger|+|equal|<k ,则说明第k大的数落在smaller数组里面,递归找smaller数组里面第 k−|larger|+|equal| 大的数(因为已经排除掉这么多个大数了,所以下一步的k要减去这个数的个数)
具体实现
class Solution {
public:
int findKthLargest(vector<int>& nums, int k) {
vector<int> smaller, larger, equal;
return findKth(nums,smaller, larger, equal,k);
}
int findKth(vector<int> nums, vector<int>& smaller, vector<int>& larger, vector<int>& equal, int k) {
smaller.clear();
larger.clear();
equal.clear();
int v = nums[nums.size()/2];
for (auto num : nums) {
if (num < v)
smaller.push_back(num);
else if (num == v)
equal.push_back(num);
else
larger.push_back(num);
}
if (k <= larger.size())
return findKth(larger,smaller, larger, equal, k);
else if (k <= larger.size() + equal.size())
return v;
else
return findKth(smaller, smaller, larger, equal, k - (larger.size() + equal.size()));
}
};
遇到的问题与改进方法
1.第k小和第k大不同,将判别条件调整一下就好
2.一开始选择主元素v时选择了第一个数,后来遇到那种降序的数组就超过了内存,懒得用随机选择,选用了中间那个数作为主元素
3.想要节省内存,所以将大等小三个数组也按引用传递下去,结果由于每次都会清零,将nums也清零了,因为nums在上一层也许是大等小三个数组的引用,所以nums没有继续用按引用传递
复杂度
时间复杂度 O(nlogn)
其他方法
利用标准库中的sort等
class Solution {
public:
int findKthLargest(vector<int>& nums, int k) {
sort(nums.begin(), nums.end());
return nums[k - 1];
}
};
排序后直接找到第k大的数,时间复杂度 O(nlogn)
class Solution {
public:
int findKthLargest(vector<int>& nums, int k) {
priority_queue<int> pq(nums.begin(), nums.end());
for (int i = 0; i < k - 1; i++)
pq.pop();
return pq.top();
}
};
利用priority_queue排序,pop掉k-1个大数之后的那个就是第k大的数