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