30:最小的K个数


avatar
bo-jwolf 2015-01-31 1.19k

面试题30

题目描述:

输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,。

输入:

每个测试案例包括2行:

第一行为2个整数n,k(1<=n,k<=200000),表示数组的长度。

第二行包含n个整数,表示这n个数,数组中的数的范围是[0,1000 000 000]。

输出:

对应每个测试案例,输出最小的k个数,并按从小到大顺序打印。

样例输入:

8 4 4 5 1 6 2 7 3 8

样例输出:

1 2 3 4

第一眼想法:排序(快排O(n*logn),但效率不高;因为空间复杂度最差情况为O(n)

正解:利用优先队列(默认有限队列priority_queue<int>为从大到小排序,priority_queue<int,vector<int>, greater<int> ?>为从大到小排序 )。那么每次将数据插入到队列中,直到

队列中数据个数大于K个。由于采用默认值。因此每次队首的数据是最大的,每次使用改值与输入数据进行比较就可以了。然后再用一个栈,按照题目要求格式输出。这样时间复杂度为O(n*logk)

#include<iostream>
#include<cstring>
#include<cstdio>
#include<string>
#include<queue>
#include<algorithm>
#include<functional>
#include<stack>
using namespace std;

const int MAX = 35;
int num[MAX], pos[MAX], str[MAX];

int main(){
	//priority_queue<int, vector<int>, greater<int> > Q;
	priority_queue<int> Q;
	int n, k, num;
	while (scanf( "%d%d", &n, &k ) != EOF ){
		while (!Q.empty()){
			Q.pop();
		}
		
		for (int i = 0; i < n; ++i){
			//cin >> num;
			scanf("%d", &num);
			if ( Q.size() < k){
				Q.push(num);
			}
			else if (Q.size() == k && num < Q.top()){
				Q.push(num);
			}
			if (Q.size() > k){
				Q.pop();
			}

		}
		stack<int>P;
		while (!Q.empty()){
			P.push(Q.top());
			Q.pop();
		}
		if (!P.empty()){
			//cout << P.top();
			printf("%d", P.top());
			P.pop();
		}
		while (!P.empty()){
			//cout << " " << P.top();
			printf(" %d", P.top());
			P.pop();
		}
		printf("\n");
	}
	return 0;
}

 

 

 

如果说上面那样说二者的效果不够明显。那么下面这题和上面类似。

但由于求得是两数组中任意二者的和再排序。根据数据范围,则实际的数据量N == n*n;如果仍然按照快排去做的话。则会TLE。

题目链接

Problem Description
还记得Gardon给小希布置的那个作业么?(上次比赛的1005)其实小希已经找回了原来的那张数表,现在她想确认一下她的答案是否正确,但是整个的答案是很庞大的表,小希只想让你把答案中最大的M个数告诉她就可以了。
给定一个包含N(N<=3000)个正整数的序列,每个数不超过5000,对它们两两相加得到的N*(N-1)/2个和,求出其中前M大的数(M<=1000)并按从大到小的顺序排列。

 

Input
输入可能包含多组数据,其中每组数据包括两行:
第一行两个数N和M,
第二行N个数,表示该序列。

 

Output
对于输入的每组数据,输出M个数,表示结果。输出应当按照从大到小的顺序排列。

 

Sample Input
4 4 1 2 3 4 4 5 5 3 6 4

 

Sample Output
7 6 5 5 11 10 9 9 8
#include<iostream>
#include<cstring>
#include<cstdio>
#include<string>
#include<queue>
#include<algorithm>
#include<functional>
#include<stack>
using namespace std;

const int MAX = 3005;
int num[MAX * MAX];
int main(){
	int n, m;
	priority_queue<int, vector<int>, greater<int> > Q;
	while (cin >> n >> m){
		for (int i = 1; i <= n; ++i){
			cin >> num[i];
		}
		while (!Q.empty())
			Q.pop();
		for (int i = 1; i <= n; ++i){
			for (int j = i + 1; j <= n; ++j){
				if ( Q.size() < m ){
					Q.push(num[i] + num[j]);
				}
				else if ( Q.size() == m){
					Q.push(num[i] + num[j]);
				}
				if (Q.size() > m){
					Q.pop();
				}
			}
		}
		stack<int> P;
		while (!Q.empty()){
			P.push( Q.top() );
			Q.pop();
		}
		cout << P.top();
		P.pop();
		while (!P.empty()){
			cout << " " << P.top();
			P.pop();
		}
		cout << endl;
	}
	return 0;
}

 

暂无评论

发表评论

相关阅读