68.把数组排成最小的数(数组、算法)。
题目:输入一个正整数数组,将它们连接起来排成一个数,输出能排出的所有数字中最小的一个。
例如输入数组{32, 321},则输出这两个能排成的最小数字 32132。
请给出解决问题的算法,并证明该算法。
思路:首先,肯定要考虑溢出问题。开始想用字符串,后来改为了用list。思路是先把第一个数字放入list,然后依次把后面的数字插入到合适的位置。
关键问题就是如何判断两个数字哪一个在前面。
①对于 353 、412这样的情况,肯定是第一个数字小的在前面
②遇到数字相同的就比较下一个数字
③那像 3、 32 这样的情况,两个数字前面相同后面不一样长的 把长的数字去掉相同的部分再跟短的数字比
如 3 、3332
3、332
3、32
3、2 后面的数字放前面
再如 321321321、321
321321、321
321、321 相等 哪个放在前面都一样
为了获取数字的每一位方便,有定义了一个结构,存放每个数字各个位上的数,以及位数的大小。整体代码如下:
/* 68.把数组排成最小的数(数组、算法)。 题目:输入一个正整数数组,将它们连接起来排成一个数,输出能排出的所有数字中最小的一个。 例如输入数组{32, 321},则输出这两个能排成的最小数字 32132。 请给出解决问题的算法,并证明该算法。 start to code = 18:42 end time = 19:47 */ #include <iostream> #include <list> using namespace std; typedef struct SeperateNum { int num[30]; //在前面的是低位 int len; }SeperateNum; SeperateNum getSeperateNum(int n) { SeperateNum s; s.len = 0; int t = n; while(t != 0) { s.num[s.len++] = t % 10; t = t / 10; } if (s.len == 0) //只有一个数字0的情况 { s.num[0] = 0; s.len = 1; } return s; } bool isBefore(SeperateNum a, int na, SeperateNum b, int nb) //a 是否应该放在 b前面 n为当前判断第几个数字 { if (b.len - nb < 0 && a.len - na < 0) //两个数字相等 或者一个数字是另一个数字复制了 n遍 321 321321321哪个放前面都一样 { return true; } else if (b.len - nb < 0 && a.len - na >= 0) //b数字比较短 且b与a的前面都相等 { return isBefore(a, na, b, 1); } else if(b.len - nb >= 0 && a.len - na < 0) //a数字比较短 { return isBefore(a, 1, b, nb); } if (a.num[a.len - na] > b.num[b.len - nb]) { return false; } else if (a.num[a.len - na] < b.num[b.len - nb]) { return true; } else //本位数字相等判断下一位 { return isBefore(a, na + 1, b, nb + 1); } } void getMinNum(int * in, int len) //输入数组 和 长度 { list<SeperateNum> lminNum; list<SeperateNum>::iterator it; SeperateNum temp = getSeperateNum(in[0]); bool isInsert = false; lminNum.push_back(temp); for (int i = 1; i < len; i++) { isInsert = false; temp = getSeperateNum(in[i]); for(it = lminNum.begin(); it != lminNum.end(); it++) { if (isBefore(temp, 1, *it, 1)) //需要插入 { lminNum.insert(it, temp); isInsert = true; break; } } if (isInsert == false) //没有在中间插入 插在最后面 { lminNum.push_back(temp); } } cout << "组合成的最小数字是:"; for(it = lminNum.begin(); it != lminNum.end(); it++) //输出最小的数字 注意判断结束要用 ‘ != ’ 不能用‘ < ’ { for(int i = it->len - 1; i >= 0; i--) { cout<< it->num[i]; } } cout<< endl; } int main() { int a[5] = {321, 321321325, 3, 32}; getMinNum(a, 4); return 0; }
查到了一个讲C++不错的网址http://www.cplusplus.com/reference/list/list/insert/
整整写了100多行,用到了自定义结构、STL、递归各种复杂的东西。用了1个多小时,还不包括思考的时间。
在网上找答案,发现人家的答案都好简洁啊。
http://blog.csdn.net/cxllyg/article/details/7659525 经验证这里的答案正确 里面还附有证明
方法相当的简单,我怎么就没有想到。 就是把两个数a、b 正反都拼一下 ab、ba 比较一下那个数小就行了。
代码里面直接用了strcmp来做这个。
#include <iostream> #include <string.h> using namespace std; const int g_MaxNumberLength=10; char* g_StrCombine1=new char[g_MaxNumberLength*2+1]; char* g_StrCombine2=new char[g_MaxNumberLength*2+1]; int compare(const void* strNumber1, const void* strNumber2) { strcpy(g_StrCombine1, *(const char**)strNumber1); strcat(g_StrCombine1, *(const char**)strNumber2); strcpy(g_StrCombine2, *(const char**)strNumber2); strcat(g_StrCombine2, *(const char**)strNumber1); return strcmp(g_StrCombine1, g_StrCombine2); } void PrintMinNumber(int *numbers, int length) { if(numbers==NULL || length<=0) return; 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]); } qsort(strNumbers, length, sizeof(char*), compare); for(int i=0; i<length; i++) cout<<strNumbers[i]; cout<<endl; for(int i=0; i<length; i++) delete[] strNumbers[i]; delete[] strNumbers; } void main() { int Num; cin>>Num; int *numbers=new int[Num]; for(int i=0; i<Num; i++) cin>>numbers[i]; PrintMinNumber(numbers, Num); getchar(); }
另一个实现:
#include <iostream> #include <string> #include <sstream> #include <algorithm> using namespace std; bool compare(const string& str1, const string &str2) { string s1=str1+str2; string s2=str2+str1; return s1<s2; } void ComArrayMin(int *pArray, int num) { int i; string *pStrArray=new string[num]; for(i=0; i<num; i++) { stringstream stream; stream<<pArray[i]; stream>>pStrArray[i]; } sort(pStrArray, pStrArray+num, compare); for(i=0; i<num; i++) cout<<pStrArray[i]; cout<<endl; delete[] pStrArray; } void main() { int Num; cin>>Num; int *pArray=new int[Num]; for(int i=0; i<Num; i++) cin>>pArray[i]; ComArrayMin(pArray, Num); }
【编程题目】把数组排成最小的数,布布扣,bubuko.com