面试题 17.14. 最小K个数
Posted 是七喜呀!
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了面试题 17.14. 最小K个数相关的知识,希望对你有一定的参考价值。
题目链接: 面试题 17.14. 最小K个数
有关题目
设计一个算法,找出数组中最小的k个数。
以任意顺序返回这k个数均可。
示例:
输入: arr = [1,3,5,7,2,4,6,8], k = 4
输出: [1,2,3,4]
提示:
0 <= len(arr) <= 100000
0 <= k <= min(100000, len(arr))
题解
法一:排序
代码一:
class Solution {
public:
vector<int> smallestK(vector<int>& arr, int k) {
sort(arr.begin(), arr.end());
vector<int> ans(k, 0);
for (int i = 0; i < k; ++i){
ans[i] = arr[i];
}
return ans;
}
};
代码二:
class Solution {
public:
vector<int> smallestK(vector<int>& arr, int k) {
sort(arr.begin(), arr.end());
return vector(begin(arr), begin(arr) + k);
}
};
法二:快速选择
参考官方题解评论区梦璃夜·天星
思路:
使用nth_element
nth_element实际上是快速选择算法的实现
void nth_element (Iterator first, Iterator first+nth, Iterator last, Compare comp);
重新排列range [first,last)中的元素,使第n个位置的元素是按排序顺序在该位置的元素。
其他元素没有任何特定的顺序,
只是第n个元素之前的元素都不大于该元素,
而第n个元素后面的元素均不小于该元素。
代码一:
class Solution {
public:
vector<int> smallestK(vector<int>& arr, int k) {
nth_element(arr.begin(), arr.begin() + k, arr.end());
return vector(arr.begin(), arr.begin() + k);
}
};
代码二:
无序的话认准 快速选择 nth_element
前n个无序
要求有序就用 部分排序 partial_sort
前n个有序
class Solution {
public:
vector<int> smallestK(vector<int>& arr, int k) {
nth_element(begin(arr), begin(arr)+k, end(arr));
return vector(begin(arr), begin(arr)+k);
}
};
法三:自建堆
class Solution {
public:
void maxHeapify(vector<int>& arr, int i, int heapSize){
int l = 2 * i + 1, r = 2 * i + 2, cur = i;
if (l < heapSize && arr[l] > arr[cur]){
cur = l;
}
if (r < heapSize && arr[r] > arr[cur]){
cur = r;
}
if (cur != i){
swap(arr[cur], arr[i]);
//调整堆的顺序
maxHeapify(arr, cur, heapSize);
}
}
void buildMaxHeap(vector<int>& arr, int heapSize){
for (int i = heapSize / 2; i >= 0; --i){
maxHeapify(arr, i, heapSize);
}
}
vector<int> smallestK(vector<int>& arr, int k) {
int n = arr.size();
vector<int> ans;
if (n == 0 || k == 0) return ans;
//构建大根堆
buildMaxHeap(arr, k);
for (int i = k; i < n; ++i){
if (arr[0] > arr[i]){
swap(arr[0], arr[i]);
//调整大根堆
maxHeapify(arr, 0, k);
}
}
for (int i = 0; i < k; ++i){
ans.push_back(arr[i]);
}
return ans;
}
};
法四:堆
class Solution {
public:
vector<int> smallestK(vector<int>& arr, int k) {
int n = arr.size();
vector<int> ans(k, 0);
if (n == 0 || k == 0){
return ans;
}
priority_queue<int> Q;
for (int i = 0; i < k; ++i){
Q.push(arr[i]);
}
for (int i = k; i < n; ++i){
if (Q.top() > arr[i]){
Q.pop();
Q.push(arr[i]);
}
}
for (int i = 0; i < k; ++i){
ans[i] = Q.top();
Q.pop();
}
return ans;
}
};
以上是关于面试题 17.14. 最小K个数的主要内容,如果未能解决你的问题,请参考以下文章
Leetcode刷题100天—面试题 17.14. 最小K个数(优先队列)—day27
Leetcode刷题100天—面试题 17.14. 最小K个数(优先队列)—day27
C++&Python描述 LeetCode 面试题 17.14. 最小K个数
LeetCode 面试题 17.14. 最小K个数(堆排,快排)/剑指 Offer 10- I. 斐波那契数列 /470. 用 Rand7() 实现 Rand10()(拒绝采样,学!!!)