程序员面试题精选100题(41)-把数组排成最小的数

以下文字摘自 http://zhedahht.blog.163.com/blog/static/25411174200952174133707/

题目:输入一个正整数数组,将它们连接起来排成一个数,输出能排出的所有数字中最小的一个。例如输入数组{32,  321},则输出这两个能排成的最小数字32132。请给出解决问题的算法,并证明该算法。

分析:这是096月份百度新鲜出炉的一道面试题,从这道题我们可以看出百度对应聘者在算法方面有很高的要求。

这道题其实是希望我们能找到一个排序规则,根据这个规则排出来的数组能排成一个最小的数字。要确定排序规则,就得比较两个数字,也就是给出两个数字mn,我们需要确定一个规则mn哪个更大,而不是仅仅只是比较这两个数字的数值哪个更大。

根据题目的要求,两个数字mn排成的数字mnnm,如果mn<nm,那么我们应该输出mn,也就是m应该排在n的前面,也就是m小于n;反之,如果nm<mnn小于m。如果mn==mnm等于n

接下来我们考虑怎么去拼接数字,即给出数字mn,怎么得到数字mnnm并比较它们的大小。直接用数值去计算不难办到,但需要考虑到的一个潜在问题是mn都在int能表达的范围内,但把它们拼起来的数字mnnm就不一定能用int表示了。所以我们需要解决大数问题。一个非常直观的方法就是把数字转换成字符串。

另外,由于把数字mn拼接起来得到的mnnm,它们所含有的数字的个数肯定是相同的。因此比较它们的大小只需要按照字符串大小的比较规则就可以了。

——————————————————————————————

代码实现其实并不需要向他实现的那么复杂。

其核心的代码是实现cmp函数。

代码如下

int front_cmp(const void *a,const void *b)
{
int first = *(int *)a;
int second = *(int *)b;
/*
while(first > 9)
first /= 10;
while(second > 9 )
second /= 10;
return first - second;
*/
static char pbuf1[21];
static char pbuf2[21];
sprintf(pbuf1,
"%d%d",first,second);
sprintf(pbuf2,
"%d%d",second,first);
return strcmp(pbuf1,pbuf2);

}

说明:1.static是为了避免多次栈中分配空间,分配21是由于max_int最大数只有10位数。

         2.sprintf函数是替代atoi的一个比较通用的方案。

再通过快速排序,即可得到答案。输出数组里面的数(连续输出,不要有空格即可)

经过测试,结果正确可行。

posted @ 2011-05-17 13:47  westfly  阅读(344)  评论(0编辑  收藏  举报