文章目录
- Question
- Ideas
- Code
Question
输入一个长度为 n
的整数数列,从小到大输出前 m
小的数。
输入格式
第一行包含整数 n
和 m
。
第二行包含 n
个整数,表示整数数列。
输出格式
共一行,包含 m
个整数,表示整数数列中前 m
小的数。
数据范围
1≤m≤n≤105
,
1≤数列中元素≤109
输入样例:
5 3
4 5 1 3 2
输出样例:
1 2 3
Ideas
Code
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1e5 + 10;
int h[N]; // 用一个数组模拟堆
int cnt; // 堆中有多少元素
int n, m;
void down(int u){
int t = u; // 父节点、两个子节点最小的值的下标
if (2 * u <= cnt && h[2 * u] < h[t]) t = 2 * u;
if (2 * u + 1 <= cnt && h[2 * u + 1] < h[t]) t = 2 * u + 1;
if (t != u){
swap(h[t], h[u]);
down(t);
}
}
int main(){
cin >> n >> m;
cnt = n;
for (int i = 1; i <= n; i ++) cin >> h[i]; // 注意下标从1开始,为了防止左孩子下标(2*t)为0
// O(N)时间复杂度建堆
for (int i = n / 2; ~i ; i --) down(i);
// 输出堆顶,最小值(小根堆)
while (m --){
cout << h[1] << ' ';
// 删除堆顶
h[1] = h[cnt];
cnt --;
down(1);
}
return 0;
}