【问题标题】:form the largest number possible in a list [duplicate]形成列表中可能的最大数字[重复]
【发布时间】:2018-06-14 20:28:23
【问题描述】:

给定一个列表,例如: [3、30、34、5、9]。 输出:9534330 编写一个程序以返回可能的最大数

在我的代码中,我在这里使用了排列:

from itertools import permutations
x = [3, 30, 34, 5, 9]
y = permutations(x)
n = len(y)
e = []
for i in y:
    a = map(str, i)
    e.append(int("".join(i)))
print "Largest Number {}".format(sorted(e)[-1])

这里 n 表示排列数的长度是 120,因为 5!。 有没有更好的方法来解决这个问题?

【问题讨论】:

    标签: python algorithm permutation


    【解决方案1】:

    按降序对所有数字进行排序是我们想到的最简单的解决方案。但这不起作用。

    例如,548 大于 60,但在输出中,60 在 548 之前。作为第二个示例,98 大于 9,但在输出中 9 在 98 之前。

    解决方案是使用任何基于比较的排序算法。因此,不要使用默认比较,而是编写一个比较函数 myCompare() 并使用它对数字进行排序。

    给定两个数字 X 和 Y,myCompare() 应该如何决定首先放置哪个数字 - 我们比较两个数字 XY(Y 附加在 X 的末尾)和 YX(X 附加在 Y 的末尾)。

    如果 XY 较大,那么在输出中,X 应该在 Y 之前,否则 Y 应该在 X 之前。

    例如,让 X 和 Y 分别为 542 和 60。要比较 X 和 Y,我们比较 54260 和 60542。由于 60542 大于 54260,我们将 Y 放在首位。

    计算排列会产生更高的时间复杂度。 python中更好的解决方案是:

    def largestNumber(A):
        maxlen = len(str(max(A)))
        if all(v == 0 for v in A):
            return '0'
        return ''.join(sorted((str(v) for v in A), reverse=True,
                          key=lambda i: i*(maxlen * 2 // len(i))))
    
    largestNumber([3, 30, 34, 5, 9])
    

    【讨论】:

    • 欢迎解释。
    • @YvesDaoust 添加了解释。希望对您有所帮助。
    • 现在清楚多了。但是关系“先于”是传递的吗?
    • 嗯,一个“明显”的例子不是证明。
    • 我不清楚关键功能。为什么需要为 lex-sorting 执行字符串的重复?为什么你不能只对数字本身的 strings 进行 lex-sort 降序处理,而不需要 maxlen 重复?关键功能也与解释没有相似之处,因为您声称将 XY 与 YX 进行比较并不是关键功能正在做的事情。进一步澄清会有所帮助。
    【解决方案2】:

    这个问题的解决方案导致了一个值得解释的有趣转变。

    假设对于给定的XY,我们想知道XYYX 中的哪一个更大。在数值上,我们想要X.10^y + YY.10^x + X 中的最大值,其中小写字母表示大写变量的位数。

    然后用一点数学,比较

    X.10^y + Y < Y.10^x + X
    

    可以改写

    X / (10^x - 1) < Y / (10^y - 1)
    

    所以XY &lt; YX 肯定是一个传递关系并定义了一个总顺序。这是一个非常好的消息,因为这意味着可以通过使用这种修改后的比较操作将问题简化为普通排序。

    现在注意X / (10^x - 1)0.XXXX... 形式的周期小数,比较0.XXXX...0.YYYY...,只要比较最长周期就足够了。因此,比较可以像普通的字符串比较一样工作,只是当到达较短字符串的末尾时,我们会循环回到第一个字符。

    例如12345 &gt; 12 因为12345 &gt; 12|12|112105 &lt; 12 因为12105 &lt; 12|12|1

    比较函数可以描述如下:

    def Cmp(X, Y):
        l= max(len(X), len(Y))
        for i in range(l):
            if X[i % len(X)] < Y[i % len(Y)]:
                return 1 # X > Y
            elif X[i % len(X)] > Y[i % len(Y)]:
                return -1 # X < Y
        return 0 # X == Y
    

    我不推荐这种特殊的实现,因为% 会很慢。

    【讨论】:

    • 记住 python2 将在 2 年后死亡。请避免给出仅限 python2 的答案。在 python3 中,语法是:from functools import cmp_to_key print(sorted(['3', '30', '34', '5', '9'], key=cmp_to_key(Precedes)))
    • 有人知道如何在 cmets 中添加换行符吗?
    • 但是你的回答很有用,2020年后所有读者都可以使用。我们现在必须忘记python2(除了那些必须维护遗留代码的人)
    • 我完全重写了这个答案,上面的 cmets 不再相关。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-10
    • 1970-01-01
    • 2012-01-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多