剑指offer32_把数组排成最小的数_题解

把数组排成最小的数

题目描述

输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323。

示例1

输入

[3,32,321]

返回值

"321323"

分析

方案一:贪心,自定义排序

自定义排序规则,对于数组中任意两个字符串a,b,如果a + b < b + a,则把a排在b的前面

字符串 xy < yx , yz < zy ,需证明 xz < zx 一定成立。

设十进制数 x, y, z 分别有 a, b, c 位,则有:
(左边是字符串拼接,右边是十进制数计算,两者等价)
xy = x * 10^b + y 
yx = y * 10^a + x
yz = y * 10^c + z
zy = z * 10^b + y

则 xy < yx 可转化为:
x * 10^b + y < y * 10^a + x
x (10^b - 1) < y (10^a - 1)
x / (10^a - 1) < y / (10^b - 1)     ①

同理, 可将 yz < zy 转化为:
y * 10^c + z < z * 10^b + y
y * (10^c - 1) < z * (10^b - 1)
y / (10^b - 1) < z / (10^c - 1)     ②

将 ① ② 合并,整理得:
x / (10^a - 1) < y / (10^b - 1) < z / (10^c - 1)
x / (10^a - 1) < z / (10^c - 1)
x (10^c - 1) < z (10^a - 1)
x * 10^c + z < z * 10^a + x
∴  可推出 xz < zx ,传递性证毕

代码

/**
1.时间复杂度:O(nlogn)
N 为最终返回值的字符数量,使用快排或内置函数的平均时间复杂度为O(NlogN),最差为 O(N^2)
2.空间复杂度:O(n)
**/
class Solution
{
public:
    string PrintMinNumber(vector<int> numbers)
    {
        vector<string> str;
        str.resize(numbers.size());
        // 转换为字符串
        transform(numbers.begin(), numbers.end(), str.begin(), [](int num) { return to_string(num); });
        // 自定义排序(lambda表达式)
        sort(str.begin(), str.end(), [](string s1, string s2) { return s1 + s2 < s2 + s1; });
		// 拼接字符串
        string ret = "";
        for (const string s : str)
        {
            ret += s;
        }
        return ret;
    }
};
posted @ 2021-01-11 20:07  RiverCold  阅读(57)  评论(0编辑  收藏  举报