原题
题目:
输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323。
Answer
思路分析
字节转化成排列组合做,用回溯法,得到所有的排列可能后再转换为int,输出最小值。
# -*- coding:utf-8 -*-
class Solution:
def PrintMinNumber(self, numbers):
# write code here
if not numbers:
return ""
res = []
path = ""
temp = [str(x) for x in numbers]
self.helper(temp, res, path)
return min(res)
def helper(self, numbers, res, path):
if not numbers:
res.append(int(path))
else:
for i in range(len(numbers)):
self.helper(numbers[:i]+numbers[i+1:], res, path+numbers[i])
优化版:
遇到这个题,全排列当然可以做,但是时间复杂度为O(n!)。在这里我们自己定义一个规则,对拼接后的字符串进行比较。
排序规则如下:
- 若ab > ba 则 a 大于 b,
- 若ab < ba 则 a 小于 b,
- 若ab = ba 则 a 等于 b;
根据上述规则,我们需要先将数字转换成字符串再进行比较,因为需要串起来进行比较。比较完之后,按顺序输出即可。
C++ Version:
class Solution {
public:
string PrintMinNumber(vector<int> numbers) {
int length = numbers.size();
if(length == 0){
return "";
}
sort(numbers.begin(), numbers.end(), cmp);
string res;
for(int i = 0; i < length; i++){
res += to_string(numbers[i]);
}
return res;
}
private:
// 升序排序
static bool cmp(int a, int b){
string A = to_string(a) + to_string(b);
string B = to_string(b) + to_string(a);
return A < B;
}
};
Python Version:
# -*- coding:utf-8 -*-
class Solution:
def PrintMinNumber(self, numbers):
# write code here
if len(numbers) == 0:
return ''
compare = lambda a, b:cmp(str(a) + str(b), str(b) + str(a))
min_string = sorted(numbers, cmp = compare)
return ''.join(str(s) for s in min_string)
Note:
- 对 C++,将 int 转换成 string 需要借助
to_string
; - 其次,值得注意的是,C++ 中空字符串不能用
''
来表示,而需要用""
来表示;这点与 python 不同,python 可以使用''
来表示空字符串; - 注意在C++中,cmp函数要是使用static进行声明,声明是静态成员函数,这样才能正确调用;
- python 中,cmp 函数可是用于str类型比较,这点倒是很。。奇特了,注意 lambda 函数的使用方式:
compare = lambda a, b:cmp(str(a) + str(b), str(b) + str(a))
; - 很巧妙的字符串组织方式:
return ''.join(str(s) for s in min_string)
;