剑指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;
}

猜你喜欢

转载自blog.csdn.net/m0_37885286/article/details/79681997