- Top k Largest Numbers
Given an integer array, find the top k largest numbers in it.
Example
Example1
Input: [3, 10, 1000, -99, 4, 100] and k = 3
Output: [1000, 100, 10]
Example2
Input: [8, 7, 6, 5, 4, 3, 2, 1] and k = 5
Output: [8, 7, 6, 5, 4]
解法1:min-heap。时间复杂度O(nlogk)。
class Solution {
public:
/**
* @param nums: an integer array
* @param k: An integer
* @return: the top k largest numbers in array
*/
vector<int> topk(vector<int> &nums, int k) {
vector<int> results;
int numSize = nums.size();
if (numSize < k) return results;
priority_queue<int, vector<int>, greater<int>> pq;
for (int i = 0; i < numSize; ++i) {
pq.push(nums[i]);
if (i >= k) pq.pop();
}
while(!pq.empty()) {
results.push_back(pq.top());
pq.pop();
}
reverse(results.begin(), results.end());
return results;
}
};
解法2:minHeap
class Solution {
public:
/**
* @param nums: an integer array
* @param k: An integer
* @return: the top k largest numbers in array
*/
vector<int> topk(vector<int> &nums, int k) {
int n = nums.size();
priority_queue<int, vector<int>, greater<int>> minHeap;
for (int i = 0; i < n; ++i) {
if (i < k) {
minHeap.push(nums[i]);
}
else {
if (nums[i] > minHeap.top()) {
minHeap.pop();
minHeap.push(nums[i]);
}
}
}
vector<int> res;
while (!minHeap.empty()) {
res.push_back(minHeap.top());
minHeap.pop();
}
reverse(res.begin(), res.end());
return res;
}
};
想了一下,解法1和解法2其实差不多。
解法 3. 先用QuickSelect找到第k大的数,然后把大于等于它的数都放到一个vector里面。注意可能有重复的数。
这里我实际上是用的找第n-k小的数(记得不是n-k+1)。
时间复杂度O(n)。记得跟QuickSort 比较,QuickSort的时间复杂度是O(nlogn)。
class Solution {
public:
/**
* @param nums: an integer array
* @param k: An integer
* @return: the top k largest numbers in array
*/
vector<int> topk(vector<int> &nums, int k) {
vector<int> result;
int numSize = nums.size();
if (numSize < k) return result;
int KthLargestNum = quickSelect(nums, 0, numSize - 1, numSize - k);
for (int i = 0; i < numSize; ++i) {
if (nums[i] >= KthLargestNum) result.push_back(nums[i]);
}
sort(result.rbegin(), result.rend());
result.resize(k); //in case nums has some duplicate elements
return result;
}
private:
int quickSelect(vector<int> &nums, int start, int end, int k) {
if (start >= end) return nums[start];
int left = start, right = end;
int pivot = nums[left + (right - left) / 2];
while (left <= right) {
while(left <= right && nums[left] < pivot) left++;
while(left <= right && nums[right] > pivot) right--;
if (left <= right) {
int temp = nums[left];
nums[left] = nums[right];
nums[right] = temp;
left++;
right--;
}
}
if (start + k -1 <= right)
return quickSelect(nums, start, right, k);
if (start + k - 1 >= left)
return quickSelect(nums, left, end, k - (left - start));
return pivot;
}
};
解法3:参考的九章。
这个模板更简洁。
class Solution {
public:
/**
* @param nums: an integer array
* @param k: An integer
* @return: the top k largest numbers in array
*/
vector<int> topk(vector<int> &nums, int k) {
int n = nums.size();
if (n == 0 || k > n) return vector<int>();
vector<int> result;
int pivot = quickSelect(nums, 0, n - 1, k);
for (int i = 0; i < nums.size(); ++i) {
if (nums[i] > pivot) result.push_back(nums[i]);
}
while(result.size() < k) {
result.push_back(pivot);
}
sort(result.rbegin(), result.rend());
return result;
}
private:
int quickSelect(vector<int> &nums, int start, int end, int k) {
if (start == end) return nums[start]; //note it is not nums[k]
int i = start, j = end;
int pivot = nums[i + (j - i) / 2];
while (i <= j) {
while(i <= j && nums[i] > pivot) {
i++;
}
while(i <= j && nums[j] < pivot) {
j--;
}
if (i <= j) {
swap(nums[i], nums[j]);
i++;
j--;
}
}
if (j - start + 1 >= k) {
return quickSelect(nums, start, j, k);
}
if (i - start + 1 <= k) {
return quickSelect(nums, i, end, k - (i - start));
}
return pivot;
//return nums[j + 1];
}
};
代码同步在
https://github.com/luqian2017/Algorithm