【編程題目】把數組排成最小的數

來源:互聯網
上載者:User

標籤: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);}

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.