(day31)牛客试题——最大数

描述

给定一个长度为n的数组nums,数组由一些非负整数组成,现需要将他们进行排列并拼接,每个数不可拆分,使得最后的结果最大,返回值需要是string类型,否则可能会溢出。

数据范围:1≤n≤100,0≤nums[i]≤10000

进阶:时间复杂度O(nlogn),空间复杂度:O(n)

示例

输入:[30,1]

返回值:"301"

输入:[2,20,23,4,8]

返回值:"8423220"

输入:[2]

返回值:"2"

输入:[10]

返回值:"10"

备注:

输出结果可能非常大,所以你需要返回一个字符串而不是整数。

 代码

from typing import List
class Solution:
    def solve(self, nums: List[int]) -> str:
        # 将每个数字转换为字符串
        nums_str = list(map(str, nums))

        # 自定义排序规则:比较 x + y 和 y + x 的字典序大小
        nums_str.sort(key=lambda x: x * 10, reverse=True)

        # 拼接排序后的字符串列表成一个字符串
        result = "".join(nums_str)

        # 处理前导零的情况,如果拼接结果的第一个字符是 '0',则说明结果为 "0"
        return "0" if result[0] == "0" else result

关键代码

nums_str.sort(key=lambda x: x*10, reverse=True)

  • sort 方法

    • sort 方法用于对列表 nums_str 进行原地排序(即不创建新的列表,直接在原列表上进行排序)。
    • sort 方法的时间复杂度为 O(nlog⁡n)O(n \log n)O(nlogn),因为它使用的是 Timsort,一种混合排序算法。
  • key 参数

    • key 参数用于指定一个函数,该函数用于生成排序依据。
    • lambda x: x*10 是一个匿名函数,用于生成排序依据。
  • lambda x: x*10

    • lambda x: x*10 是一个匿名函数,接受一个参数 x,并返回 x 自身重复 10 次的字符串。
    • 例如,如果 x'3',则 x*10 生成 '3333333333';如果 x'30',则 x*10 生成 '3030303030'
    • 这样做的目的是为了确保字符串的长度足够,使得字符串比较能够正确反映不同长度字符串的相对大小。
  • reverse=True

    • reverse=True 指定排序顺序为降序(从大到小)。
    • 这意味着在排序时,比较函数返回的结果将会以降序排列。

 

具体实现原理

通过使用 x*10,我们将每个字符串扩展为更长的字符串,从而确保排序时按照字符串的字典序比较长度足够长的字符串。这样可以正确处理不同长度的字符串,并且确保较短的字符串不会因为缺少位数而被错误比较。

举例说明:

  • 假设有 nums_str = ['3', '30', '34', '5', '9']
  • 使用 lambda x: x*10,我们得到排序依据为 ['3333333333', '3030303030', '3434343434', '5555555555', '9999999999']
  • 按照字典序进行降序排序,我们得到排序顺序为 ['9', '5', '34', '3', '30']

这样,通过 key=lambda x: x*10,我们能够正确处理和排序不同长度的字符串,以生成最大拼接结果。

详细步骤分析:

  1. 将数字转换为字符串

    • 使用 map(str, nums) 将输入的每个数字转换为字符串形式,以便进行字符串比较。
  2. 自定义排序规则

    • 使用 sort 函数对字符串数组进行排序。这里 key=lambda x: x*10 确保数字的位数足够进行比较,因为 Timsort 是稳定的排序算法,可以使用倍数技巧保持字典序正确。
    • reverse=True 表示按从大到小的顺序排序。
  3. 拼接结果

    • 将排序后的字符串数组拼接成一个最终的结果字符串。
  4. 处理前导零

    • 如果结果字符串的第一个字符是 0,则说明结果为 "0"(所有数字都是零的情况)。

 

  • 15
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值