最大组合数问题

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];
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值