【转帖】把数组排成最小的数

    转自: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,它们所含有的数字的个数肯定是相同的,因此比较它们的大小只需要按照字符串大小的比较规则就可以了

    基于这个思路,我们可以写出下面的代码:

// Maxinum int number has 10 digits in decimal system
const int g_MaxNumberLength = 10;


// String buffers to combine two numbers
char* g_StrCombine1 = new char[g_MaxNumberLength * 2 + 1];

char* g_StrCombine2 = new char[g_MaxNumberLength * 2 + 1];

// Given an array, print the minimum number by combining all numbers in the array

void PrintMinNumber(int* numbers, int length)
{
if(numbers == NULL || length <= 0) return;

// Convert all numbers as strings
char** strNumbers = (char**)(new int[length]);

for(int i = 0; i < length; ++i)
{
strNumbers[i] = new char[g_MaxNumberLength + 1];
sprintf(strNumbers[i], "%d", numbers[i]);
}

// Sort all strings according to algorithm in function compare
qsort(strNumbers, length, sizeof(char*), compare);


for(int i = 0; i < length; ++i)
printf("%s", strNumbers[i]);
printf("\n");

for(int i = 0; i < length; ++i)
delete[] strNumbers[i];
delete[] strNumbers;
}

// Compare two numbers in strNumber1 and strNumber2
// if [strNumber1][strNumber2] > [strNumber2][strNumber1],
// return value > 0
// if [strNumber1][strNumber2] = [strNumber2][strNumber1],
// return value = 0
// if [strNumber1][strNumber2] < [strNumber2][strNumber1],
// return value < 0
int compare(const void* strNumber1, const void* strNumber2)

{
// [strNumber1][strNumber2]
strcpy(g_StrCombine1, *(const char**)strNumber1);

strcat(g_StrCombine1, *(const char**)strNumber2);

// [strNumber2][strNumber1]
strcpy(g_StrCombine2, *(const char**)strNumber2);

strcat(g_StrCombine2, *(const char**)strNumber1);

return strcmp(g_StrCombine1, g_StrCombine2);
}

posted on 2011-10-27 16:16  白草黒尖  阅读(1796)  评论(0编辑  收藏  举报