標籤:style blog http color os io for ar
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:42end 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);}