输入一个非负整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。
示例 1:
输入: [10,2] 输出: "102"
示例 2:
输入: [3,30,34,5,9] 输出: "3033459"
提示:
0 < nums.length <= 100说明:
输出结果可能非常大,所以你需要返回一个字符串而不是整数拼接起来的数字可能会有前导 0,最后结果不需要去掉前导 0
一、题解
1.1 思路
本题求拼接起来的最小数字,是一个排序问题。
排序的判断规则:
若拼接字符串 x + y > y + x,则 x > y;
若拼接字符串 x + y < y + x,则x < y.
算法流程:
1、初始化:字符串列表strs,保存各数字的字符串形式;
2、排序:将字符串按照以上规则进行排序;
3、拼接:将拼接好的字符串返回
复杂度分析:
1、时间复杂度:O(NlogN),无论是内置函数还是快排的平均时间复杂度为O(NlogN)
2、空间复杂度:O(N)
1.2 代码(内置函数)
```java
class Solution {
public String minNumber(int[] nums) {
int len = nums.length;
String[] strs = new String[len];
for(int i = 0; i < len; i++){
strs[i] = String.valueOf(nums[i]);
}
Arrays.sort(strs, (x, y) -> (x + y).compareTo((y + x)));
StringBuilder sb = new StringBuilder();
for(int i = 0; i < len; i++){
sb.append(strs[i]);
}
return sb.toString();
}
}
```
1.3 代码(快排)
快排的Partition()方法是先找一个基准,记为value,然后从右往左找小于基准的,即(x +value) .compareTo(value + x) >= 0,即x >=value的时候,继续往前找;从左往右也是类似的,y <= value的时候,继续往后找
class Solution {
public String minNumber(int[] nums) {
int len = nums.length;
String[] strs = new String[len];
for(int i = 0; i < len; i++){
strs[i] = String.valueOf(nums[i]);
}
quickSort(strs, 0, len - 1);
StringBuilder sb = new StringBuilder();
for(int i = 0; i < len; i++){
sb.append(strs[i]);
}
return sb.toString();
}
private void quickSort(String[] strs, int left, int right){
if(left >= right){
return;
}
int pivot;
pivot = Partition(strs, left, right);
quickSort(strs, left, pivot - 1);
quickSort(strs, pivot + 1, right);
}
private int Partition(String[] strs, int l, int r){
if(l == r){
return l;
}
int start_index = l;
String value = strs[l];
while(l < r){
//从右往左找小的,就是说strs[r] >= strs[value]时,r--
while(l < r && (strs[r] + value).compareTo(value + strs[r]) >= 0){
r--;
}
//从左往右找大的,就是说strs[l] <= strs[value]时,l++
while(l < r && (strs[l] + value).compareTo(value + strs[l]) <= 0){
l++;
}
swap(strs, l, r);
}
swap(strs, l, start_index);
return l;
}
private void swap(String[] strs, int i, int j){
String tmp = strs[i];
strs[i] = strs[j];
strs[j] = tmp;
}
}