劍指Offer——面試題33:把數組排成最小的數

把數組排成最小的數


題目:輸入一個正整數數組,把數組裏所有數字拼接起來排成一個數,打印能拼接出的所有數字中最小的一個。例如輸入數組{3,32,321},則打印出這三個數字能排成的最小數字爲321323。

輸入:{3,32,321}

輸出:321323

思路:1、主要的思路是利用遞歸去判斷兩個數字m和n,合併後是mn大還是nm大。
2、在這裏需要注意如果2個由int類型表示的數字,在合併後很可能會超出int類型能表示的範圍,所以這裏還是一個隱形的大數問題。
3、對於大數問題最好的解決辦法是利用字符串來解決,並且mn和nm這2個數字的位數都是一樣的,更可以用字符串來解決。
總結:於是問題就變成遞歸的每次比較2個數字是合併前大還是合併後大,然後再輸出最終合併的數字,該數字就是最小的數字

Ps:這裏還是需要注意一個事情,我們在對數組進行排列前,要先對數組進行一次排序,讓小的數字排在前面,這樣對後面判斷mn和nm比較有優勢,舉個例子來說:1 3 5 4 2,那麼如果不排序的話,只能輸出13542,而排序後的數組是:1 2 3 4 5,對應輸出結果是12345,12345<13542,這就是在合併前排序的重要性

/*
題目:把數組排成最小的數
*/

#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;

string minMerge(string str1,string str2){
    //這裏有可能str1和str2都是int或者long long類型範圍內表示不了的數,所以只能一個字符一個字符的比較
    for (int i = 0; i < str1.size(); i++){
        if ((str1[i] - '0') < (str2[i] - '0')){
            return str1;
        }
        else if ((str1[i] - '0') > (str2[i] - '0')){
            return str2;
        }
    }
    return str1;
}

string PrintMinNumber(vector<int> numbers) {
    string str1;
    string str2;
    sort(numbers.begin(), numbers.end());
    if (numbers.size() == 0){
        return str1;
    }
    str1 = to_string(numbers[0]);
    for (int i = 1; i < numbers.size(); i++){
        str2 = to_string(numbers[i]);
        //用str1保存合併後最小的數
        str1 = minMerge(str1 + str2, str2 + str1);
    }
    return str1;
}

int main(){
    int n;
    cin >> n;
    vector<int> numbers;
    int temp;
    for (int i = 0; i < n; i++){
        cin >> temp;
        numbers.push_back(temp);
    }
    cout << PrintMinNumber(numbers);
    system("pause");
    return 0;
}
發佈了50 篇原創文章 · 獲贊 45 · 訪問量 11萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章