sort 九度教程第11题 Hash思想 + 以空间换时间思想

题目链接

Problem Description
给你n个整数,请按从大到小的顺序输出其中前m大的数。
Input
每组测试数据有两行,第一行有两个数n,m(0<n,m<1000000),第二行包含n个各不相同,且都处于区间[-500000,500000]的整数。
Output
对每组测试数据按从大到小的顺序输出前m大的数。
Sample Input
5 3
3 -35 92 213 -644
Sample Output
213 92 3

解题思路
下面是机试指南中的分析:

本例中,如果使用排序来解决该题,由于待排序数字的数量十分庞大(1000000),即使使用时间复杂度为 O(nlogn)的快速排序,其时间复杂度也会达到千万数量级,而这在一秒时限内是不能被我们所接受的,所以这里,我们并不能使用快速排序来解决本题。
该例题面限定了输入的数字一定是[-500000,500000]区间里的整数,且各不相同。若利用一个数组分别统计每一种数字是否出现,其空间复杂度依旧在题目的限定范围内。且统计出现数字当中较大的 m 个数字,也仅需要从尾至头遍历这个数组,其时间复杂度仍在百万数量级,所以该解法是符合我们要求的。

要点:
1、大量数据输入,使用cin超时;
2、输入数据中出现负数,为避免把负数当做数组下标,我们应该额外加上一个偏移量。
AC代码:

#include<iostream>
#include<stdio.h>
using namespace std;
#define offset 500000//偏移量
int myhash[1000001];

int main() {
	int n, m;
	while (scanf("%d%d",&n,&m)!=EOF) {
		for (int i = -500000; i <= 500000; i++) myhash[i + offset] = 0;
		while (n--) {
			int x;
			scanf("%d", &x);//使用cin会超时
			myhash[x + offset] = 1;
		}
		for (int i = 500000; i >= -500000; i--) {//从大的数向小的数遍历,找出前m大的数
			if (myhash[i + offset] == 1) {
				cout << i;
				m--;
				if (m != 0) cout << " ";
				else {
					cout << endl;
					break;
				}
			} 
		}
	}
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章