只是为了另一种方式:
from itertools import cycle, islice
def extender(n):
def extend(x):
s = str(x)
return "".join(islice(cycle(s), n))
return extend
def biggest_number(input):
if (len(input) == 0):
return 0
extend = extender(len(str(max(input))) * 2)
s = sorted(input, key=extend, reverse=True)
return int("".join(map(str, s)))
本质上,您获取数组的每个元素并根据需要通过重复使它们具有相同的长度。然后你做一个字典排序。 (此时数字排序是相同的,但完成后我们需要字符串。)
例如,对于[3, 30, 34, 5, 9],我们发现最长的数字是 2 位,因此我们通过根据需要重复数字来将所有数字扩展为 3 位。这些是使用的键:
[333, 303, 343, 555, 999]
然后我们对结果进行排序、降序和组装:
[9, 5, 34, 3, 30]
9534330
直觉来自于“选择具有最大前导数字的数字”。问题在于我们应该如何处理领带。例如,为什么我们要在 30 之前选择 3?答案是,在 3 之后可能出现的最大数字是另一个 3。(如果有更大的数字可用,我们早就选择了。)因此,将 3 视为“333333...”有助于我们选择正确对象,真爱。类似的问题:为什么我们会选择 10 而不是 100?这使我们意识到 10 之后的最佳结果是另一个以 10 开头的数字。(我们已经选择了 11 或更多。)因此将其视为“10101010...”和“100100100100...”。原来,你只需要扩展到n*2个数字,其中n是最长数字的长度。
我意识到这有点令人困惑。我写了一个测试来确保这一切都是正确的。 (它与您的原始代码进行比较。)
from functools import cmp_to_key
import random
def largestNumber(nums):
numStr = [str(i) for i in nums]
def str_cmp(x, y):
if y+x < x+y: return -1
elif y+x > x+y: return 1
else: return 0
numStr.sort(key=cmp_to_key(str_cmp))
return "".join(numStr).lstrip('0') or '0'
for i in range(1000000):
input = [random.randint(0, 1000) for _ in range(random.randint(0, 100))]
if biggest_number(input) != int(largestNumber(input)):
print("FAILED: {}".format(input))
if i % 100 == 0:
print(i)
我还没有找到不起作用的输入。我相当确信这段代码是正确的。
说了这么多,我不知道你为什么不想只使用cmp_to_key。 :-)