用堆排序实现线性时间查找前K大数字

1004. 寻找前k大的数(选做)
Total:339Accepted:44
   
Time Limit: 1sec    Memory Limit:256MB
Description

<b>选做</b><br>

你的任务是写一个程序来找出N个整数里面前K大的整数,输出按照降序排列。

你可以通过百度了解如何快速找出这K个整数,可以找到时间复杂度为O(N*lgK)的方法。

如果你实在搜不到,ftp上面有个txt文件大概讲了三种方法的思路,可以去看看。

如果面试问到了这个题,优先使用第一种思路,当然如果面试官允许你把三种思路都讲完的话,那也是不错的(前提是你不要自己打脸…要理解它们的复杂度为什么是那样)。

Input

输入有多个测试用例,每个测试用例是两行:

第1行是两个整数N和K,中间用空格隔开(N ≥ K)

第2行有N个整数,每两个数字中间用空格隔开

输入以EOF结束

Output

对于每一个测试用例,输出一行,K个整数,就是它的前K大的整数,按照降序排列输出,每两个数字之间用空格隔开,最后一个数字后面没有空格,有换行。

Sample Input
Copy sample input to clipboard
5 23 2 4 1 5
Sample Output
5 4

/*包括去重复和不去重复两种,主要是建立最小堆
*/

#include <iostream>
#include <cstdio>
#include <memory.h>

using namespace std;

//调整堆
void HeapAdjust(int *a, int ¤t, int low, int high)
{
	int large;
	large = 2 * low + 1; //左儿子
	while (large <= high) {
		if (large < high && a[large] > a[large+1])
			large++;
		if (current <= a[large])
			break;
		else {
			//继续调整堆
			a[low] = a[large];
			low = large;
			large = 2 * low + 1;
		}
	}
	a[low] = current;
}

void build_heap(int *a, int size)
{
	int current;
	//建堆,从(size - 2)/2开始 到0
	for (int low = (size - 2)/2; low >= 0; low--)
	{
		//记录当前值
		current = a[low];
		HeapAdjust(a, current, low, size - 1);
	}
}
void HeapSort(int *a, int size)
{
	int current;
	//建立堆
	build_heap(a, size);

	for (int i = size - 1; i > 0; i--)
	{
		current = a[i];
		a[i] = a[0];
		HeapAdjust(a, current, 0, i - 1);
	}
}

int main()
{
	/*  去重复
	//int a[1000];
	int k;
	int n;
	int size;
	int find[10000];
	int in_it[1000] = {0};
	int index = 0;
	//cout << "请输入要找的规模: ";
	while (scanf("%d", &n) != EOF) {
		//memset(in_it, 0, 100000*sizeof(int));
		//cout << "请输入要找第几大的数字: ";

		cin >> k;
		size = k;
		int *a = new int[k];
		//cout << "输入找的序列: " << endl;
		for (int i = 0; i < n; i++)
			cin >> find[i];

		//将不重复的数字放进堆中
		bool ok = false;
		
		int j = 0;
		
		for (int i = 0; i < n && ok == false; i++)
		{
			bool init = false;
			for (int m = 0; m < index; m++) {
				if (in_it[m] == find[i])
					init = true;
			}
			if (!init)
			{
				a[j] = find[i];
				j++;
				in_it[index] = find[i];
				index++;
				
				if (j == k)
					ok = true;
			}
		}

		//建堆
		build_heap(a, size);

		//开始寻找
		for (int i = 0; i < n; i++)
		{
			bool init = false;
			for (int j = 0; j < index; j++) {
				if (in_it[j] == find[i])
					init = true;
			}
			if (init)
				continue;
			else
			{
				if (find[i] > a[0])
				{
					a[0] = find[i];
					build_heap(a, size);
				}
			}
		}
		HeapSort(a, size);
		//cout << "前K大数字为:" << endl;
		cout << a[0];
		for (int i = 1; i < k; i++)
			cout << " " << a[i];
		cout << endl;
		delete []a;
	}
	*/
	//system("pause");


	//不去重复
	int k;
	int n;
	int size = 0;
	int num;
	//cout << "请输入要找的规模: ";
	while (scanf("%d", &n) != EOF) {
		//memset(in_it, 0, 100000*sizeof(int));
		//cout << "请输入要找第几大的数字: ";
		cin >> k;
		size = 0;
		int *a = new int[k];
		//cout << "输入找的序列: " << endl;
		for (int i = 0; i < n; i++)
		{
			cin >> num;
			if (size < k)
			{
				a[size] = num;
				size++;
				continue;
			}
			if (i == k) build_heap(a, size);
			if (num > a[0])
			{
				a[0] = num;
				//build_heap(a, size);
				HeapAdjust(a, num, 0, k - 1);
			}
		}

		HeapSort(a, size);
		//cout << "前K大数字为:" << endl;
		cout << a[0];
		for (int i = 1; i < k; i++)
			cout << " " << a[i];
		cout << endl;
		delete []a;
	}
	return 0;
	
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值