1.1.1题目描述
设有n个正整数,将它们连成一排,组成一个最大的多位整数。
例如:n=3时,3个整数13,312,343,连成的最大整数为34331213.
1.2.2思路描述
对于该问题,因为当给的几个数确定了,那么最后的组合数的位数也确定了,要使组合数最大,那么就应该将数字大的数放在高位。我们想到,对多个具有相同位数的数,其值最大的数也就是数字最大的数,那么以此为基础,我们可以将给出的几个数全部变为位数相同的数,然后进行排序,就可以得到最后的组合方法。
首先选定多个数中最大一个数,求其位数做为每个数的补齐标准。而对于补齐操作,因为我们要求组合最大数,那么要确保补齐后的数仍然具有补齐前的比较性,也就是补齐之后,所补在末尾的数应该替代补之前的末尾数的比较性。那么结合该思路,补齐位数时就应该在该数的末尾补上原来的个位数。从而对补齐后的数进行排序,就可以得到最终结果。
1.2.3遇到的问题
最开始进行补齐的时候,想的比较简单,直接进行的是补0操作,比如对8和28就直接进行8*10补0,但是后面发现结果不对,考虑之后发现下面的情况:21和2,如果直接补0后排序得到21和20,那么排序组合后就是212,但是实际应该是221。说明直接补0考虑地不够周全。
后来思考了以下,发现问题出在补0的话就抹掉了原来的数的末尾的“2”的比较意义,而是直接赋予0,使其固定具有最小的比较权重。总结了以下,发现当补位的时候,为了保持原尾数的比较意义,就应该把最后的尾数补进去,这样即完成了位数补齐的操作,又保留了尾数的比较意义。此时再看21和2,按照新的补齐方式,就应该补为22,21,排序输出后就是221,输出正确。
#include<iostream>
#include<cmath>
using namespace std;
int countw(int num) //计算输入的数的位数
{
int count=1;
while(num>=10)
{
num=num/10;
count++;
}
return count;
}
void func(int num[],int n,int maxcount) //求得最大组合数
{
int arr[n+1],time,temp;
for(int i=1;i<=n;i++) //复制给辅助数组
{
arr[i]=num[i];
if(countw(arr[i])<maxcount) //辅助数组中补齐位数
{
time=maxcount-countw(num[i]);
while(time)
{
temp=arr[i]%10; //补上原数的个位数
arr[i]=arr[i]*10+temp;
time--;
}
}
}
for(int i=1;i<n;i++) //对辅助数组进行排序
{
int temp,k;
k=i;
for(int j=i;j<=n;j++)
if(arr[j]>arr[k])
k=j;
swap(arr[k],arr[i]);
swap(num[k],num[i]); //原数组同时进行交换
}
}
int main()
{
int n,max=0;
int maxcount;
cout<<"输入整数个数:";
cin>>n;
int *num=new int[n+1];
cout<<"输入"<<n<<"个整数:";
for(int i=1;i<=n;i++)
cin>>num[i];
for(int i=1;i<=n;i++) //找到n个整数中的最大位数
if(num[i]>max)
max=num[i];
maxcount=countw(max);
func(num,n,maxcount);
cout<<"最大组合数为:";
for(int i=1;i<=n;i++)
cout<<num[i];
}