机试算法讲解: 第6题 给n个整数,按从大到小的顺序,输出前m大的整数

/*
问题:给n个整数,按从大到小的顺序,输出前m大的整数
0<m,n<1000000,每个整数[-500000,500000]
输入:
5 3
3 -35 92 213 -644
输出:
213 92 3 
思路:
先按从小到大用快排排好序,然后输出排好序的数组从最后开始输出m个即可

关键:
1 已经达到千万数量级,1秒不能解决,必须用哈希,因为数字的范围达到百万级
2 哈希针对的是输入数值处于特定范围的问题,建立一个范围大小的数组,建立hash[x] = x出现多少次的映射
3 对于定义较大容量的数组,放在函数体外,这样用全局变量,内存会比较充足
4 对于区间为负的,需要设定下标补偿值
*/

#include <stdio.h>
#include <stdlib.h>

#define POS 500000
int iHash[1000001] = {0};

int main(int argc,char* argv[])
{
	int n,m,i;
	while(EOF!=scanf("%d%d",&n,&m) && m <= n && m > 0 && m < 1000000 && n > 0 && n < 1000000 )
	{
		for(i = 0; i < n ;i++)
		{
			int iValue;
			scanf("%d",&iValue);
			if(iValue < -500000 || iValue > 500000)
			{
				return 0;
			}
			else
			{
				iHash[iValue + POS] = 1;//下标和值存在某种一元函数关系
			}
		}
		for(i = 500000 ; i >= -500000 ; i--)
		{
			if(iHash[i + POS]==1)
			{
				m--;
				printf("%d ",i);
			}
			//if(m)//应该是m=0打印空格
			if(0==m)
			{
				printf("\n");
				break;
			}
		}
		//printf("\n");
	}
	system("pause");
	getchar();
	return 0;
}

/*
#include <stdio.h>
#include <memory.h>
#include <stdlib.h>

int partition(int *A,int low,int high)
{
	int iPos = A[low];
	while(low < high)
	{
		while(low < high && A[high] > iPos)
		{
			high--;
		}
		A[low] = A[high];
		while(low < high && A[low] < iPos)
		{
			low++;
		}
		A[high] = A[low];
	}
	A[low] = iPos;
	return low;
}

void quickSort(int *A,int low,int high)
{
	if(low < high)
	{
		int iPos = partition(A,low,high);
		quickSort(A,low,iPos-1);
		quickSort(A,iPos+1,high);
	}
}




int main(int argc,char* argv[])
{
	int m,n,i;
	while(EOF!=scanf("%d %d",&n,&m) && n >= m && n > 0 && n < 1000000 && m > 0 && m < 1000000)
	{
		int *iArr = (int*)malloc(n*sizeof(int));
		for( i = 0 ;i < n ; i++ )
		{
			int iValue;
			scanf("%d",&iValue);
			if(iValue < -500000 || iValue > 500000)
			{
				free(iArr);
				return 0;;
			}
			else
			{
				*(iArr+i) = iValue;
			}
		}
		quickSort(iArr,0,n-1);//0~m-1,n-1 是1 ,n-2 是2 , n-m是  m
		for(i = n-1;i >= (n-m); i--)
		{
			printf("%d ",iArr[i]);
		}
		free(iArr);
	}
	system("pause");
	getchar();
	return 0;
}

 */

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值