题目描述
- 输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323。
知识点:
- 数组,全排列,排序,贪心
方法一:暴力破解
- 假设n个整数的索引值为[0,1,…,n-1],对这n个索引全拍了,再对每次全排列进行一次组织结果,选取最小的值为答案。
- 时间复杂度:O(n*n!),全排列时间复杂度为N!,每次排列结果需要遍历一次nums数组
- 空间复杂度:O(1)
- 代码为:
class Solution {
public:
void perm(int pos, vector<int> &num, string &ret) {
if (pos + 1 == num.size()) {
// 一次全排列的结果
string tmp = "";
for (int val : num) {
tmp += to_string(val);
}
ret = min(ret, tmp);
return;
}
for (int i = pos; i < num.size(); ++i) {
swap(num[pos], num[i]);
perm(pos+1, num, ret);
swap(num[pos], num[i]);
}
}
string PrintMinNumber(vector<int> nums) {
string ret(nums.size(), '9'); // nums.size()个'9'
perm(0, nums, ret);
return ret;
}
};
方法二:贪心,自定义排序
- 方法一出现太多无关排列,如果存在字符串 a,b。a+b<b+a,则我们希望a在b前。可以自定义排序规则。
- 时间复杂度:O(nlogn),采用了排序
- 空间复杂度:O(n)
- 代码:
class Solution {
public:
string PrintMinNumber(vector<int> nums) {
vector<string> str;
for (int val : nums) str.push_back(to_string(val));
sort(str.begin(), str.end(), [](string a, string b) {
return a + b < b + a;
});
string ret = "";
for (string s : str) ret += s;
return ret;
}
};
Java实现自定义排序
- 两次循环,外循环确定每个下标,内存换用来将外循环确定下标元素进行比较。小则冒泡,大则不变。
public String PrintMinNumber(int [] numbers) {
ArrayList<String> list = new ArrayList();
int num1;
int num2;
int tmp;
for (int i = 0; i< numbers.length - 1; i++){
for (int j = i+1; j < numbers.length; j++){
num1 = Integer.valueOf(String.valueOf(numbers[i])+String.valueOf(numbers[j]));
num2 = Integer.valueOf(numbers[j] + ""+numbers[i]);
if (num1 > num2){
tmp = numbers[j];
numbers[j] = numbers[i];
numbers[i] = tmp;
}
}
}
String str = "";
for (int t : numbers){
str += String.valueOf(t);
}
return str;
}