剑指 45. 把数组排成最小的数 - 难度中等

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的相对位置不变;

思路:

  1. 两个字符串的首位不同时,将首位数字小的排在前面;
  2. 两个字符串的首位相同时,将二者拼接,比较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/

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值