题目1504:把数组排成最小的数

题目描述:

输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323。

输入:

输入可能包含多个测试样例。
对于每个测试案例,输入的第一行为一个整数m (1<=m <=100)代表输入的正整数的个数。
输入的第二行包括m个正整数,其中每个正整数不超过10000000。

输出:

对应每个测试案例,
输出m个数字能排成的最小数字。

样例输入:
3
23 13 6
2
23456 56
样例输出:
13236
2345656
看到这个题目,简单分析了下,断定当各个整数的最高位越小的放在前面即可。为了方便操作,选择用字符串存储读入的各个整数。代码如下:
#include<stdio.h>
#include<string.h>
int main()
{
     int i,j,flag,m;
     char num[100][10],temp[10];
     while ( scanf ( "%d" ,&m)!=EOF)
     {
         for (i=0;i<m;i++)
             scanf ( "%s" ,num[i]);
         for (i=1;i<m;i++)
         {
             flag=0;
             for (j=0;j<m-i;j++)
                 if ( strcmp (num[j],num[j+1])>0)    //为了编码方便,采用了改进的冒泡排序算法
                 {
                     strcpy (temp,num[j]);
                     strcpy (num[j],num[j+1]);
                     strcpy (num[j+1],temp);
                     flag=1;
                 }
             if (!flag) break ;
         }
         for (i=0;i<m;i++)
             printf ( "%s" ,num[i]);
         printf ( "\n" );
     }
     return 0;
}
但是提交结果为WA。细细分析了下,上面的代码只适用于各个整数最高位不同或最高位相同且位数相同的情况,更一般的情况并没有考虑到。思考良久,仍未能找到较好的解决办法,百度查看来博友的文章后,豁然开朗,为了便于这一算法思想对以后的自己能有更深的启发意义,遂在此博文一篇。算法的基本思路是对于a,b两个整数,如果ab<ba,那么就应该将a放在b的前面,依据这一点对数组进行排序即可。改进的代码如下:
#include<stdio.h>
#include<string.h>
int main()
{
     int i,j,flag,m;
     char num[100][10],temp1[20],temp2[20];
     while ( scanf ( "%d" ,&m)!=EOF)
     {
         for (i=0;i<m;i++)
             scanf ( "%s" ,num[i]);
         for (i=1;i<m;i++)
         {
             flag=0;
             for (j=0;j<m-i;j++)
             {
         strcpy (temp1,num[j]);
         strcpy (temp2,num[j+1]);
         strcat (temp1,num[j+1]);
         strcat (temp2,num[j]);
         if ( strcmp (temp1,temp2)>0)
                 {
                     strcpy (temp1,num[j]);
                     strcpy (num[j],num[j+1]);
                     strcpy (num[j+1],temp1);
                     flag=1;
                 }
         }   
             if (!flag) break ;
         }
         for (i=0;i<m;i++)
             printf ( "%s" ,num[i]);
         printf ( "\n" );
     }
     return 0;
}
此算法的正确性证明,参见 http://blog.csdn.net/xianliti/article/details/5649876http://blog.csdn.net/wuzhekai1985/article/details/6704902
另外,虽然最先的思路是错误的,但是对于算法性能的进一步优化还是有不小的启示。改进的排序算法代码如下:
for(i=1;i<m;i++)
        {
            flag=0;
            for(j=0;j<m-i;j++)
            {
        if(num[j][0]>num[j+1][0])     //各个整数的最高位数不同时就可以决定两个数的相对位置
        {
            strcpy(temp1,num[j]);
                        strcpy(num[j],num[j+1]);
                        strcpy(num[j+1],temp1);
                        flag=1;
        }
        else if(num[j][0]==num[j+1][0])   //而当两个整数的最高位相同时,因为其位数不同带来比较上的复杂性,我们采用比较ab与ba的大小
        {
            strcpy(temp1,num[j]);
            strcpy(temp2,num[j+1]);
            strcat(temp1,num[j+1]);
            strcat(temp2,num[j]);
            if(strcmp(temp1,temp2)>0)
                    {
                        strcpy(temp1,num[j]);
                        strcpy(num[j],num[j+1]);
                        strcpy(num[j+1],temp1);
                        flag=1;
                    }
        }
        }    
            if(!flag) break;
        }

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值