(剑指Offer)面试题33:把数组排成最小的数
题目:
输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323。
思路:
1、全排列
求出数组中所有数字的全排列,然后把每个全排列拼起来,求出拼出来的数字的最大值。
2、定义新的排序规则
如果两个数字m,n拼接成mn和nm,如果mn<nm,那么m应该排在n的前面,我们定义此时m小于n,如果mn=nm,我们定义m等于n。
可以考虑将数字转成字符串,一来防止数字拼接时的溢出,二来字符串的拼接和比较容易实现。
由于把数字m和n拼接起来得到mn和nm,它们的位数一定是相同的,因此比较它们的大小只需按照字符串大小的比较规则即可。
代码:
#include <iostream> #include <string.h> #include <stdio.h> #include <algorithm> using namespace std; const int g_MaxNumberLength=10; char* g_strCombine1=new char[2*g_MaxNumberLength+1]; char* g_strCombine2=new char[2*g_MaxNumberLength+1]; int compare(const void* strNumber1,const void* strNumber2){ char* str1=(char*)strNumber1; char* str2=(char*)strNumber2; sprintf(g_strCombine1,"%s%s",str1,str2); sprintf(g_strCombine2,"%s%s",str2,str1); return strcmp(g_strCombine1,g_strCombine2); } void printMinNumber(int* numbers,int length){ if(numbers==NULL || length<=0) return; char** strNumbers=new char*[length]; for(int i=0;i<length;i++){ strNumbers[i]=new char[g_MaxNumberLength+1]; sprintf(strNumbers[i],"%d",numbers[i]); } 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; } int main() { int numbers[]={3,32,321}; int length=sizeof(numbers)/sizeof(numbers[0]); printMinNumber(numbers,length); return 0; }
在线测试OJ:
http://www.nowcoder.com/books/coding-interviews/8fecd3f8ba334add803bf2a06af1b993?rp=2
AC代码:
class Solution { public: static bool compare(int a,int b){ string strNum1=to_string(a); string strNum2=to_string(b); return (strNum1+strNum2)<(strNum2+strNum1); } string PrintMinNumber(vector<int> numbers) { string result; if(numbers.empty()) return result; sort(numbers.begin(),numbers.end(),compare); for(unsigned int i=0;i<numbers.size();i++) result+=to_string(numbers[i]); return result; } };