杭电1280——以空间换时间 前m大的数

杭电1280——前m大的数

还记得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

思路:
1.初一看,这个题目很简单,只要 ( 双层循环 + 排序 )就可以解决。
但是排序是用 选择排序、冒泡排序、插入排序还是快速排序呢?
这个题目的陷阱就在用排序会超时,即使你用C++内的sort()函数(改进版的快速排序)
2.思路换一换,能否不用排序就可以按顺序输出呢?
这里提供一个思想 “ 用空间换时间 ” 就是用一个很大的数组,初始化为 0 ,数组的下标表示待排序的数字,数组的值表示待排序中这个下标值的个数。(可能听起来有点懵,没关系,看代码更好理解)

代码展示:

#include<stdio.h>
#include <iostream>
#include <algorithm>
#include<string.h>
using namespace std;
int main()
{
    int m,n;
    int i,j;
    while (scanf("%d%d",&n,&m) != EOF)
    {
        int a[3001];
        int sum[10001];		//定义一个很大的数组
        memset(sum,0,sizeof(sum));		//数组初始化全部为 0
        for (i=0;i<n;i++)	//循环输入数字
            scanf("%d",&a[i]);
        for (i=0;i<n;i++)	
            for (j=i+1;j<n;j++)
                sum[a[i] + a[j]]++;	//循环遍历求和,和为数组下标,数组值为相同和的个数
        i = 10000;	//从大到小遍历数组
        while (m)
        {
        	//注释部分为另一种方法
            /*if (sum[i] && m != 1)
            {
                printf("%d ",i);
                m--;
                sum[i]--;
            }
            if (sum[i] && m == 1)
            {
                printf("%d\n",i);
                m--;
            }
            if (!sum[i])
                i--;*/
                
                while (sum[i] && m)	//循环输出,当sum[i] = 1时,输出 1个i;当sum[i] = 3时,输出  3 个i; 直到 sum[i] = 0
                {
                    if (m != 1)
                        printf("%d ",i);
                    if (m == 1)
                        printf("%d\n",i);
                    sum[i]--;
                    m--;
                }		
                i--;	//当 sum[i] = 0 ,下标自减。由于前面初始化 sum[] 为0,下标 != a[i]+a[j] 的,a[下标] = 0.
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43557810/article/details/87381024