[Algorithmic Toolbox学习笔记][week3]一个列表中的数字所能构成的最大数问题

问题描述:如何用一个数组里面的数字去组成一个最大的数。

比如我们有[1, 3, 5],那么这些数字能够构成的最大数则为531。

由此可见,我们可以将数组中的数字从大到小排序然后在拼成数字,则会得到这些数字所能构成的最大数。如果用Python3来实现的话,代码如下:

def findLargestNumber(number_list):
    number_list.sort()
    res = ''
    for num in number_list:
        res = str(num) + res
    return (int(res))

number_list = [8, 7, 2, 9, 5, 1]
largest_number = findLargestNumber(number_list)
print('当前数字能构成的最大数为:', largest_number)

存在的问题:

如果我们有新的一组数组,其中包含了十位数甚至百位数的时候,通过上面的代码则无法得到最大数。请看以下例子:

number_list = [10, 68, 75, 7, 21, 12]

运行上面的代码我们会得到其最大数为:75682112107  [75,68,21,12,10,7]

可是实际上我们会发现这个数组能够组成的真正最大数为:77568211210。那如何优化代码去获得真正的最大数呢?

优化思路:

当数组中出现了十位以上的数字的时候,代码的正确性即出现了问题。那么我们可以看看当数组中只有两个数字的时候,我们会如何判断。

比如我们有一个数组:[23, 8]。我们会用238和823做比较,可以知道823更大。

那如果数组中有三个数字呢,又如何进行比较?还是可以两个两个进行比较。
比如针对数组[4, 21, 33]
421>214,我们可以4排在21前面
433>334,我们可以4排在33前面
2133<3321,我们可以33排在21前面
因此最后我们可以得知,新的排序为[4, 33, 21],其组成的最大数为43321
同理针对[11, 5, 8, 23],根据以上方法将每个数字与其余数字进行如上比较的话,我们可以知道8>5>23>11,因此我们可以得到最大数852311

因此,数组中两个数字的比较方式为:
假设x为数组中的一个数字,y为剩余数字中的任意一个。那么系统则需要去比较xy和yx的大小,如果xy大于yx,那么x排在y前面;如果yx大于xy,那么y则需要排在x前面。当遍历完所有数字后,我们则会得到一个新的排序列表。

所以,要获得这个问题的正确答案,我们只需要解决:如何让一个数组按照我们自定义的排序规则进行排序

要解决这个问题我们需要用到cmp_to_key()方法。关于此方法的详细解释请参考我的另一篇文章:
[Python3][cmp_to_key函数][关于list的自定义排序]_Karen_AMPM的博客-CSDN博客

在我们得到一个按照自定义排序规则排序的列表后,便可以输出最大数了。参考代码如下:

from functools import cmp_to_key

def custom_compare(a, b):
    value1 = str(a) + str(b)
    value2 = str(b) + str(a)

    if value1 < value2:
        return 1
    elif value1 > value2:
        return -1
    else:
        return 0


def findLargestNumber(number_list):
    # 根据自定义的排序规则重新对列表进行排序
    newls = sorted(number_list, key=cmp_to_key(custom_compare), reverse=True)

    # join and return
    res = ''
    for num in newls:
        #print(num)
        res = str(num) + res
    return (int(res))

number_list = [10, 68, 97, 9, 21, 12]
largest_number = findLargestNumber(number_list)
print('当前数字能构成的最大数为:', largest_number)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值