描述
给定一个长度为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(nlogn)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
,我们能够正确处理和排序不同长度的字符串,以生成最大拼接结果。
详细步骤分析:
-
将数字转换为字符串:
- 使用
map(str, nums)
将输入的每个数字转换为字符串形式,以便进行字符串比较。
- 使用
-
自定义排序规则:
- 使用
sort
函数对字符串数组进行排序。这里key=lambda x: x*10
确保数字的位数足够进行比较,因为 Timsort 是稳定的排序算法,可以使用倍数技巧保持字典序正确。 reverse=True
表示按从大到小的顺序排序。
- 使用
-
拼接结果:
- 将排序后的字符串数组拼接成一个最终的结果字符串。
-
处理前导零:
- 如果结果字符串的第一个字符是
0
,则说明结果为 "0"(所有数字都是零的情况)。
- 如果结果字符串的第一个字符是