假设我有一组正整数;我想操纵顺序,以便结果数组的串联是可能的最大数字。例如,[97, 9, 13]
会产生99713
; [9,1,95,17,5]
会产生9955171
。我不确定答案。
答案 0 :(得分:11)
sorted(x, cmp=lambda a, b: -1 if str(b)+str(a) < str(a)+str(b) else 1)
答案 1 :(得分:8)
直观地说,我们可以看到反向排列的单位数字会导致最大数字:
>>> ''.join(sorted(['1', '5', '2', '9'], reverse=True))
'9521'
所以反向排序应该有效。当输入中存在多位数片段时会出现问题。在这里,直觉再次允许我们在9
和95
之前17
之前订购1
,但为什么这样做呢?同样,如果它们的长度相同,那么如何对它们进行排序就很清楚了:
95 < 99
96 < 97
14 < 17
然后,诀窍是“扩展”较短的数字,以便可以将它们与较长的数字进行比较,并且可以按字典顺序自动排序。实际上,您需要做的就是重复代码段超出最大长度:
9
和95
:改为比较999
和9595
,因此999
优先。1
和17
:改为比较111
和1717
,因此1717
优先。132
和13
:改为比较132132
和1313
,因此132132
优先。23
和2341
:改为比较232323
和23412341
,因此2341
优先。这是有效的,因为python只需比较两个片段,直到它们在某处不同;并且它(重复)在比较两个片段时需要跳过的匹配前缀,以确定他们需要在哪个顺序中形成一个最大的数字。
您只需要重复一个片段,直到它长于输入中的最长片段* 2,以确保在比较两个片段时可以找到第一个不匹配的数字。
您可以使用key
的{{1}}参数执行此操作,但您需要先确定代码段的最大长度。使用该长度,您可以“填充”排序键中的所有片段,直到它们超过最大长度:
sorted()
其中def largestpossible(snippets):
snippets = [str(s) for s in snippets]
mlen = max(len(s) for s in snippets) * 2 # double the length of the longest snippet
return ''.join(sorted(snippets, reverse=True, key=lambda s: s*(mlen//len(s)+1)))
将自己的代码段填充为长度超过s*(mlen//len(s)+1)
。
这给出了:
mlen
请注意,这个解决方案是a)3行简短,b)也适用于Python 3而不必求助于>>> combos = {
... '12012011': [1201, 120, 1],
... '87887': [87, 878],
... '99713': [97, 9, 13],
... '9955171': [9, 1, 95, 17, 5],
... '99799713': [97, 9, 13, 979],
... '10100': [100, 10],
... '13213': [13, 132],
... '8788717': [87, 17, 878],
... '93621221': [936, 21, 212],
... '11101110': [1, 1101, 110],
... }
>>> def test(f):
... for k,v in combos.items():
... print '{} -> {} ({})'.format(v, f(v), 'correct' if f(v) == k else 'incorrect, should be {}'.format(k))
...
>>> test(largestpossible)
[97, 9, 13] -> 99713 (correct)
[1, 1101, 110] -> 11101110 (correct)
[936, 21, 212] -> 93621221 (correct)
[13, 132] -> 13213 (correct)
[97, 9, 13, 979] -> 99799713 (correct)
[87, 878] -> 87887 (correct)
[1201, 120, 1] -> 12012011 (correct)
[100, 10] -> 10100 (correct)
[9, 1, 95, 17, 5] -> 9955171 (correct)
[87, 17, 878] -> 8788717 (correct)
和c)不强制解决方案(这就是functools.cmp_to_key()
选项确实)。
答案 2 :(得分:5)
提示一:你连接字符串,而不是整数。
提示二:itertools.permutations()
。
答案 3 :(得分:3)
import itertools
nums = ["9", "97", "13"]
m = max(("".join(p) for p in itertools.permutations(nums)), key = int)
你可以使用itertools.permutations作为提示,并在使用join函数连接它们之后使用max函数的key参数(它告诉应用于每个元素的函数以决定最大值)。
开始使用字符串会更容易。
答案 4 :(得分:2)
我不喜欢蛮力的做法。对于大型集合,它需要大量的计算。
您可以为sorted内置方法编写自己的比较函数,该函数将根据您在函数中放入的任何逻辑返回任何对的排序参数。
示例代码:
def compareInts(a,b):
# create string representations
sa = str(a)
sb = str(b)
# compare character by character, left to right
# up to first inequality
# if you hit the end of one str before the other,
# and all is equal up til then, continue to next step
for i in xrange(min(len(sa), len(sb))):
if sa[i] > sb[i]:
return 1
elif sa[i] < sb[i]:
return -1
# if we got here, they are both identical up to the length of the shorter
# one.
# this means we need to compare the shorter number again to the
# remainder of the longer
# at this point we need to know which is shorter
if len(sa) > len(sb): # sa is longer, so slice it
return compareInts(sa[len(sb):], sb)
elif len(sa) < len(sb): # sb is longer, slice it
return compareInts(sa, sb[len(sa):])
else:
# both are the same length, and therefore equal, return 0
return 0
def NumberFromList(numlist):
return int(''.join('{}'.format(n) for n in numlist))
nums = [97, 9, 13, 979]
sortednums = sorted(nums, cmp = compareInts, reverse = True)
print nums # [97, 9, 13, 979]
print sortednums # [9, 979, 97, 13]
print NumberFromList(sortednums) # 99799713
答案 5 :(得分:1)
嗯,总是有蛮力的方法......
from itertools import permutations
lst = [9, 1, 95, 17, 5]
max(int(''.join(str(x) for x in y)) for y in permutations(lst))
=> 9955171
或者这是@Zah的答案的改编,它接收整数列表并返回一个整数,如问题中所述:
int(max((''.join(y) for y in permutations(str(x) for x in lst)), key=int))
=> 9955171
答案 6 :(得分:1)
你可以通过一些巧妙的排序来做到这一点。
如果两个字符串长度相同,请选择两个字符串中的较大字符串。容易。
如果它们的长度不同,请确定如果将最佳组合附加到较短的组合中,结果会是什么。由于较短的一切必须等于或小于它,您可以通过将短的一个附加到自身来确定这一点,直到它与较长的一个相同。一旦它们长度相同,就像以前一样进行直接比较。
如果第二个比较相等,你已经证明较短的字符串不可能比较长的字符串更好。根据与它配对的内容,它可能会变得更糟,所以应该首先考虑的时间越长。
def compare(s1, s2):
if len(s1) == len(s2):
return -1 if s1 > s2 else int(s2 > s1)
s1x, s2x = s1, s2
m = max(len(s1), len(s2))
while len(s1x) < m:
s1x = s1x + s1
s1x = s1x[:m]
while len(s2x) < m:
s2x = s2x + s2
s2x = s2x[:m]
return -1 if s1x > s2x or (s1x == s2x and len(s1) > len(s2)) else 1
def solve_puzzle(seq):
return ''.join(sorted([str(x) for x in seq], cmp=compare))
>>> solve_puzzle([9, 1, 95, 17, 5])
'9955171'
>>> solve_puzzle([97, 9, 13])
'99713'
>>> solve_puzzle([936, 21, 212])
'93621221'
>>> solve_puzzle([87, 17, 878])
'8788717'
>>> solve_puzzle([97, 9, 13, 979])
'99799713'
这比运行所有排列要有效得多。