LeetCode Offer 45. Combine numbers into the smallest number
algo
链接:剑指 Offer 45. 把数组排成最小的数 - 力扣(LeetCode)
输入: [10,2]
输出: “102”
10 比 2 小,因为 1 比 2 小。
输入: [3,30,34,5,9]
输出: “3033459”
30 比 3 小,因为否则 3 后面肯定接的一位比 0 大。如果是 32 呢?如果数组中还有一个 1 开头的,那么似乎应该先接 3,但是注意如果有 1 开头的,则应该早就被用过了。所以 32 还是比 3 小。33 呢?应该和 3 是一样的,拼出来都是 333。但是 34 肯定比 33 和 3 都大了。
我们不能直接用字符串的比较大小,因为那样 32 > 3。我们要逐位比较,即 3 = 3,而位数少的那个数字补前面的相同数字,即 32 < 33。
另一种比较的方式更简单粗暴,即直接比较字符拼接结果,绝对是更好的办法,即比较 x + y 与 y + x,这里 x 和 y 是数字的字符串表示。
def compare(x, y):
x, y = str(x), str(y)
s, t = x + y, y + x
# functools.cmp_to_key() 需要返回 -1、0、1
return -1 if s < t else 0 if s == t else 1
使用 functools.cmp_to_key
:
from functools import cmp_to_key
class Solution:
def minNumber(self, nums: List[int]) -> str:
def compare(x, y):
n1, n2 = x + y, y + x
return -1 if n1 < n2 else 0 if n1 == n2 else 1
return ''.join(sorted([str(n) for n in nums], key=cmp_to_key(compare)))
也可以用快速排序:
from random import randint
class Solution: # quicksort
def minNumber(self, nums: List[int]) -> str:
def compare(x, y):
return x + y < y + x
def partition(nums, l, r):
p = randint(l, r)
pivot = nums[p]
nums[l], nums[p] = nums[p], nums[l]
i, j = l + 1, r
while i <= j:
x, y = str(nums[i]), str(pivot)
if x + y < y + x:
i += 1
continue
x = str(nums[j])
if x + y >= y + x:
j -= 1
continue
nums[i], nums[j] = nums[j], nums[i]
nums[l], nums[j] = nums[j], nums[l]
return j
def quicksort(nums, l, r):
if l < r:
k = partition(nums, l, r)
quicksort(nums, l, k - 1)
quicksort(nums, k + 1, r)
quicksort(nums, 0, len(nums) - 1)
return ''.join(map(lambda n: str(n), nums))
Last update :
May 23, 2023
Created : May 23, 2023
Created : May 23, 2023