原题如下:
Given a list of non negative integers, arrange them such that they form the largest number.
For example, given [3, 30, 34, 5, 9]
, the largest formed number is 9534330
.
Note: The result may be very large, so you need to return a string instead of an integer.
思路1:
观察两个数的占位规则,可以得到如下规律:
左边的数比右边的数靠前,上边的数比下边的数靠前
99=9 | 98 | 97 | 96 | 95 | 94 | 93 | 92 | 91 | 90 |
89 | 88=8 | 87 | 86 | 85 | 84 | 83 | 82 | 81 | 80 |
…… | |||||||||
29 | 28 | 27 | 26 | 25 | 24 | 23 | 22=2 | 21 | 20 |
19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11=1 | 10 |
于是可能有这样一种方案:
1.首先求每个数的最高位,首先依照上表中的列顺序可以直接得出占位顺序;
2.对于最高位相同的情况:
(1)如果两数位数相同,直接比较大小即可得出结论;
(2)而对于两数位数不同的情况,那么我起初是利用上表中对角线的性质,在较短数的后面补位,直接添加最高位数值,如“1234”和“123”则在“123”末尾添“1”,那么最就得到1234>1231,但依此实现之后,提交测试有例外出现,如“121”和“12”补齐之后将出现121=121,但实际情况是12占位应在121之前,除此之外还有98和989,989占位应该在98之前,因此不可一概而论。
(3)所以,我猜想补齐时应该直接对两数都进行补齐,如“12”和“121”,应该补为“121212”和“121121”,而“989”和“98”应补为“989989”和“989898”,可以得到符合要求的排列。
上述思路实现时需要使用对数函数,对求得指数取最小公倍数然后进行补齐。
思路2
1.首先求与每个数等长的10的整数次方幂。
2.根据每个数的整数次方幂将两个数组合,如a和b,如果ab>ba,那么a>b,反之b>a。
上述思路实现如下:
class Solution{
public:
string largestNumber(vector<int> &num) {
string rst;
std::stringstream out;
int zero=0;
for(vector<int>::iterator iter=num.begin();iter!=num.end();++iter)
if(*iter==0) ++zero;
for(vector<int>::iterator iter=num.begin();iter!=num.end();++iter)
{
vector<int>::iterator max=iter;
for(vector<int>::iterator tempiter=iter+1;tempiter!=num.end();++tempiter)
if(!compare1(*max,*tempiter))
max=tempiter;
int temp=*iter;
*iter=*max;
*max=temp;
out<<*iter;
}
out>>rst;
if(zero==num.size())
return "0";
else
return rst;
}
bool compare1(int int1,int int2)
{
int num1=1,num2=1;
int rm1,rm2;
rm1=int1/num1;
rm2=int2/num2;
while(rm1>9||rm2>9)
{
if(rm1>9)
{
num1*=10;
rm1=int1/num1;
}
if(rm2>9)
{
num2*=10;
rm2=int2/num2;
}
}
int t1,t2;
t1=int1*num2*10+int2;
t2=int2*num1*10+int1;
if(t1>=t2)
return true;
else
return false;
}
};
其他需要注意的地方:
1.在类似思路1表格分析时,忽略了0的情况,即所有数都是0的情况
2.使用简单选择排序时,需要考虑0,9,8,7……的特殊情况
3.程序设计时,良好的测试素质很重要
2015-01-18