1. 题目描述
输入一个非负整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。
示例 1:
输入: [10,2]
输出: “102”
示例 2:
输入: [3,30,34,5,9]
输出: “3033459”
提示:
0 < nums.length <= 100
说明:
输出结果可能非常大,所以你需要返回一个字符串而不是整数
拼接起来的数字可能会有前导 0,最后结果不需要去掉前导 0
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/ba-shu-zu-pai-cheng-zui-xiao-de-shu-lcof
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
2. 题解
1、快速排序
思路:
- 开辟一个字符串数组,将nums元素以字符串形式存入该数组;
- 对字符串数组排序,排序规则如下:
对字符串 a 和 b,对 a 和 b 进行拼接,若 a+b > b+a,则说明 a应该排在b的右边,反之,也成立。 - 拼接排序后的字符串数组的字符串作为结果返回;
分析:
这道题的巧妙之处在于排序规则的设定,这个排序规则有对应的证明(见参考链接),这里的排序可以自己写一个快排实现,也可以调用内置函数实现。
代码实现1:自己写快速排序算法
/**
* @param {number[]} nums
* @return {string}
*/
var minNumber = function(nums) {
if(nums.length === 1){
return nums[0].toString();
}
//开辟一个字符串数组
const strs = new Array(nums.length);
let t = 0;
for(let num of nums){
strs[t++] = num.toString();
}
//对字符串数组排序
quickSort(strs, 0, strs.length-1);
//拼接字符串数组的字符串作为结果
let res = "";
for(let str of strs){
res += str;
}
return res;
};
function quickSort(strs, left, right){
if(left >= right){
return;
}
let i = left;
let j = right;
let baseStr = strs[left];
while(i != j){
//右边, strs[j] > baseStr
while(i != j && strs[j]+baseStr > baseStr+strs[j]){
j--;
}
//左边, strs[i] <= baseStr
while(i != j && strs[i]+baseStr <= baseStr+strs[i]){
i++;
}
//左右交换
if(i != j){
let tmp = strs[i];
strs[i] = strs[j];
strs[j] = tmp;
}
}
//和基准字符串交换
strs[left] = strs[i];
strs[i] = baseStr;
//左子数组
quickSort(strs, left, i-1);
//右子数组
quickSort(strs, i+1, right);
}
时间复杂度:O(n*logn);
空间复杂度:O(n),开辟的字符串数组;
参考:https://leetcode-cn.com/problems/ba-shu-zu-pai-cheng-zui-xiao-de-shu-lcof/solution/mian-shi-ti-45-ba-shu-zu-pai-cheng-zui-xiao-de-s-4/
代码实现2:使用内置的sort函数,但是自己定义排序规则
对于 js 数组的sort函数,对参数a和b:
- 若sort(a,b)返回的值小于0,则a排在b前面;
- 若sort(a,b)返回的值大于0,则a排在b后面;
- 若sort(a,b)返回的值等于0,则a和b的相对位置不变;
思路:
- 两个字符串的首位不同时,将首位数字小的排在前面;
- 两个字符串的首位相同时,将二者拼接,比较2种拼接后的结果。
/**
* @param {number[]} nums
* @return {string}
*/
var minNumber = function(nums) {
if(nums.length === 1){
return nums[0].toString();
}
//开辟字符串数组
const strs = new Array(nums.length);
for(let num of nums){
strs.push(num.toString());
}
//对字符串数组进行排序
strs.sort((s1, s2)=>{
//1. 当首位不同时,首先比较首位
if(s1.charAt(0) !== s2.charAt(0)){
return s1.charAt(0) - s2.charAt(0);
}
//2. 首位相同时,比较拼接后的结果
let tmp1 = s1.concat(s2);
let tmp2 = s2.concat(s1);
let n = tmp1.length + tmp2.length;
let index = 0;
while(index < n){
if(tmp1.charAt(index) !== tmp2.charAt(index)){
return tmp1.charAt(index) - tmp2.charAt(index);
}
index++;
}
//返回0表示a和b的相对位置不变
return 0;
});
//返回拼接结果
return strs.join("");
};
参考:https://leetcode-cn.com/problems/ba-shu-zu-pai-cheng-zui-xiao-de-shu-lcof/solution/pythonjie-jue-tong-su-yi-dong-by-compreh-6b9z/