1.题目描述
输入一个非负整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。
示例 1:
输入:[10,2]
输出:“102”
示例 2:
输入:[3,30,34,5,9]
输出:“3033459"
2.思路分析
此题求拼接起来的最小数字,本质上是一个排序问题。设数组 nums 中任意两数字的字符串为 x 和 y ,则规定 排序判断规则 为:
- 若拼接字符串 x + y > y + x ,则 x “大于” y ;
- 反之,若 x + y < y + x ,则 x “小于” y ;
x “小于” y 代表:排序完成后,数组中 x 应在 y 左边;“大于” 则反之。
根据以上规则,套用任何排序方法对 nums 执行排序即可。
算法流程:
- 初始化: 字符串列表 strs,保存各数字的字符串格式;
- 列表排序: 应用以上 “排序判断规则” ,对 strs 执行排序;
- 返回值: 拼接 strs 中的所有字符串,并返回。
3.解答
class Solution {
//快速排序 + 自定义比较规则
public String minNumber(int[] nums) {
//将整数型数组转换为字符型数组
String[] numsString = new String[nums.length];
for(int i = 0; i < nums.length; i++){
numsString[i] = String.valueOf(nums[i]);
}
//快速排序
quickSort(numsString, 0, numsString.length - 1);
//返回结果
StringBuilder res = new StringBuilder();
for(String s : numsString){
res.append(s);
}
return res.toString();
}
//辅助方法:快速排序
public void quickSort(String[] numsString, int start, int end){
if(start < end){
//将索引0作为基准
int pivot = start;
//定义排序端点
int low = start, high = end;
//从两端开始排序
while(low < high){
while(low < high && (numsString[high] + numsString[pivot]).compareTo(numsString[pivot] + numsString[high]) >= 0){
high--;
}
while(low < high && (numsString[low] + numsString[pivot]).compareTo(numsString[pivot] + numsString[low]) <= 0){
low++;
}
swap(numsString, low, high);
}
//交换基准元素
swap(numsString, pivot, low);
//递归排序
quickSort(numsString, start, low);
quickSort(numsString, low + 1, end);
}
}
//交换两个元素
public void swap(String[] numsString, int i, int j){
String temp = numsString[i];
numsString[i] = numsString[j];
numsString[j] = temp;
}
}
- 时间复杂度 O(NlogN) : N 为最终返回值的字符数量( strs 列表的长度 ≤N );使用快排或内置函数的平均时间复杂度为 O(NlogN) ,最差为 O(N^2)。
- 空间复杂度 O(N) : 字符串列表 strsstrs 占用线性大小的额外空间。