趣味算法------拼数

题目描述


设有 n 个正整数 a 1…a n ,将它们联接成一排,相邻数字首尾相接,组成一个最大的整数。

输入格式
第一行有一个整数,表示数字个数 n。

第二行有 n 个整数,表示给出的 n 个整数 a i。

输出格式
一个正整数,表示最大的整数。

输入输出样例
输入 1

3
13 312 343

输出 1
34331213


输入 2
4
7 13 4 246

输出 2
7424613
输入第一行表示输入数字个数为 3,第二行再给出 3 个整数;首先将 3 个整数进行首尾相接,一个整数位置不变的情况下,将其他整数进行连接组成最大的整数。例如输出 34331213:343 为其中数字最大的值,其次时 312,最后接上 13 即可得出最大整数。

思路解析:
         

        简单来说这道题目的就是将n个数组合拼接求出组合的最大值。这道题有许多不同的方法,比图第一个是暴力求解,也就是将所有的可能都枚举出来,然后一个一个比较,第二是使用深度优先搜索来解决,但是当数据太多时,这两种浪费的时间太多,所以我们需要另一种方法。

        假如数据只有7,12时呢?有712和127来比较,如果有7,12,13呢?我们先比较前两个数字,712,127,发现712大,7和12不需要交换位置,然后比较12,13,发现1213<1312,需要交换位置变为7,13,12,最后组合就是71312。

        现在按照这个思路我给大家出一组数据。(请在草稿纸上演练)

         7,12,13,42,56,53,31。

        有没有发现比较熟悉。。。。。。。

        这就是我们在早期说过的冒泡排序,可以在往期文章中了解,只不过交换位置判定条件从两个数字之间的大小变成两个数字组合方案的最大值决定。

具体代码:

#include<stdio.h>

#include<math.h>

int fun(int n)

{

    int count = 0;

    while (n)

    {

        count++;

        n /= 10;

    }

    return count;

}//求数字的位数。

int check(int n, int m)

{  

    int count1 = n * pow(10, fun(m)) + m;//count1的值是nm组合

    int count2 = m * pow(10, fun(n)) + n;//count2的值是mn组合

    if (count1 > count2)

        return 1;

    return 0;

}

int main(void)

{

    int n;

    int arr[100] = { 0 };

    scanf("%d", &n);

    for (int i = 0; i < n; i++)

        scanf("%d", &arr[i]);//数据输入。

    for(int i = 0;i<n;i++)

        for (int j = 0; j < n - i - 1; j++)

            if (check(arr[j+1], arr[j]))

            {

                int t = arr[j + 1];

                arr[j + 1] = arr[j];

                arr[j] = t;

            }//“冒泡”排序

    for (int i = 0; i < n; i++)

        printf("%d", arr[i]);//按顺序逐个打印。

}

        

注意:

        pow()函数“属于”math.h,传入两个参数,比如pow(n,m)的返回值是n的m次幂,但是要注意返回值非整型。

        我们为什么最后不直接打印一个整数呢(组合),而是要按数组顺序打印?这是因为在正常情况下刷题和比赛网站判断正确与否是看显示屏上输出的内容和答案是不是一样,换而言之,

答案打印1213和依次打印1,2,1,3没有什么区别。

        实际上我们判断数字需不需要交换还可以看两个相同位上的数字,比如7,17。7显然比1大,所以直接是717,但是逐位判断时间复杂度还会增加,不过当数据量太多时相比起优先搜索和暴力枚举还是很快的。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值