NYOJ 448 寻找最大数 解题报告

本文介绍了一种算法问题——寻找最大数。通过删除指定数量的数字来形成一个新数,使其值最大。文章提供了递归与非递归两种实现方式,并通过示例详细解释了算法流程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

寻找最大数

时间限制:1000 ms  | 内存限制:65535 KB

难度:2

描述

请在整数 n中删除m个数字,使得余下的数字按原次序组成的新数最大,

比如当n=92081346718538m=10时,则新的最大数是9888

 

输入

第一行输入一个正整数T,表示有T组测试数据
每组测试数据占一行,每行有两个数n,mn可能是一个很大的整数,但其位数不超过100位,并且保证数据首位非0m小于整数n的位数)

输出

每组测试数据的输出占一行,输出剩余的数字按原次序组成的最大新数

样例输入

2

92081346718538 10

1008908 5

样例输出

9888

98

 

题目连接:http://acm.nyist.net/JudgeOnline/problem.php?pid=448


之前训练时,遇见过一道名为《删数》的题目,差别就是那个让求最小的数,这个让找最大的数。

由于只能从给定的数字中删掉确定数目的数字,每位数字之间不允许交换,所以先考虑最大数字的特点,即尽量让大数在高位

给定数字为一个N位数,删掉其中M位(M<=N),使得到的(N-M)位数的值尽可能大。其实也就是从一个N位数中取出(N-M)个数,使得到的数尽量大。

按照上述的两个思想,就是说,取每一位数时,从给定数中都要取最大的数。这样,取数的过程中保证每一位都是最大,这样结果也必然是最大的。

下面举例说明:

从source_number:105789中删去3位数,所得数字放在result_num中。

先从source_number取得result_num的第一位(按从左往右记数)。

 

             数位: 1    2     3    4    5    6

Source_num:1  0  5  7  8  9

第一步:取得7,之后source_num变为89。只能从source_num的前4位(length_source –fetch_num + 1length_source为源数的长度,fetch_num为取数的个数)中取,这样不会导致取数之后,剩余的数字不够取的情况。

第二步:取得8,source_num变为9。

第三步:取得9,结束。

Result_num为:789。

不难发现,取数的过程是递归的,即每次都是取最大的那个数,所以用递归写程序较简单。

下面两种写法的思想是相同的,只是实现方法不同。

递归写法:

  1. #include <cstdio>  
  2. #include <iostream>  
  3. #include <cstring>  
  4.   
  5. using namespace std;  
  6.   
  7. char number[105];  
  8. char result[105];  
  9.   
  10. void fetch(char num[], int fetch_num, int count)  
  11. {  
  12.     int i, max, length;  
  13.     if (fetch_num == 0)  
  14.     {  
  15.         result[count] = '\0';  
  16.         return ;  
  17.     }  
  18.     else  
  19.     {  
  20.         length = strlen(num);  
  21.         max = 0;  
  22.         for (i = 1; i < length - fetch_num + 1; ++i)  
  23.         {  
  24.             if (num[i] > num[max])  
  25.             {  
  26.                 max = i;  
  27.             }  
  28.         }  
  29.         result[count++] = num[max];  
  30.         fetch(num + max + 1, fetch_num - 1, count);  
  31.     }  
  32. }  
  33.   
  34. int main()  
  35. {  
  36.     int test_num, del_num, length;  
  37.     scanf("%d", &test_num);  
  38.     while (test_num--)  
  39.     {  
  40.         scanf("%s %d", number, &del_num);  
  41.         length = strlen(number);  
  42.         fetch(number, length - del_num, 0);  
  43.         printf("%s\n", result);  
  44.     }  
  45.     return 0;  
  46. }  

非递归:

  1. #include <cstdio>  
  2. #include <iostream>  
  3. #include <cstring>  
  4.   
  5. using namespace std;  
  6.   
  7. char number[105];  
  8. char result[105];  
  9.   
  10. int main()  
  11. {  
  12.     int i, test_num, del_num, length, start, max, count, fetch_num;  
  13.     scanf("%d", &test_num);  
  14.     while (test_num--)  
  15.     {  
  16.         scanf("%s %d", number, &del_num);  
  17.         length = strlen(number);  
  18.         fetch_num = length - del_num;  
  19.         start = 0;  
  20.         count = 0;  
  21.         while (fetch_num--)  
  22.         {  
  23.             max = start;  
  24.             for (i = start + 1; i < length - fetch_num; ++i)  
  25.             {  
  26.                 if (number[i] > number[max])  
  27.                 {  
  28.                     max = i;  
  29.                 }  
  30.             }  
  31.             result[count++] = number[max];  
  32.             start = max + 1;  
  33.         }  
  34.         result[count] = '\0';  
  35.         printf("%s\n", result);  
  36.     }  
  37.     return 0;  
  38. }  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值