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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章