zoukankan      html  css  js  c++  java
  • 剑指offer_45_把数组排成最小的数

    把数组排成最小的数

    题目链接:https://leetcode-cn.com/problems/ba-shu-zu-pai-cheng-zui-xiao-de-shu-lcof/

    题目内容:

    输入一个非负整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。

    示例 1:

    输入: [10,2]
    输出: "102"
    

    示例 2:

    输入: [3,30,34,5,9]
    输出: "3033459"
    

    提示:

    • 0 < nums.length <= 100

    说明:

    • 输出结果可能非常大,所以你需要返回一个字符串而不是整数
    • 拼接起来的数字可能会有前导 0,最后结果不需要去掉前导 0

    题目解析

    题目解析内容来自于题解中Krahetsbigkjp97

    分析

    题目的意思首先要明确,不是说把列表中每个数拆分开,而是,将数组合起来,组成一个最小的数。

    这就转换成了让这个列表按照组合后数字最小的模式排序。也就是说,要定一个规则,使得列表中的数字按照这个规则从小到大排序。

    现在我们就来找这个排序规则

    这里放一个示例,供大家理解。

    test_list = [3, 30, 34, 5, 9]  # 示例列表
    

    由题意,当 '30' + '3' = '303', '3' + '30' = '330' 时,'303' < '330', 则可知 '30' + '3' < '3' + '30', 也即 30 应该在数组按照规则排序后应排在 3 前面。

    同理, '30' + '34' = '3034', '34' + '30' = '3430', '3034' < '3430', 则 '30' + '34' < '34' + '30', 即 30 在 34 前面。

    照此逻辑,可以类推。

    则可以得出这个排序规则:x + y < y + x ===> x < y

    根据这个规则,使用任何一种排序方法都可以对 指定列表进行排序,从而得到最小的排列结果。

    Picture1.png

    算法流程:
    1. 初始化:根据数字列表生成字符串列表
    2. 字符串列表排序:根据上面发现的规则进行字符串列表的排序
    3. 返回:拼接字符串列表为字符串,并返回
    复杂度分析:
    • 时间复杂度 O(NlogN): N 为最终返回值的字符数量(字符串列表 的长度 <= N); 使用快排或者内置函数的平均时间复杂度为O(NlogN), 最差为 O(N2)
    • 空间复杂度 O(N): 字符串列表 占用线性大小的额外空间
    代码

    快排方式

    class Solution:
        def minNumber(self, nums):
            def fast_sort(strs):
                if len(strs) <= 1:
                    return strs
                less, greater = [], []
                p = strs.pop()
                for i in strs:
                    if i + p < p + i:
                        less.append(i)
                    else:
                        greater.append(i)
                print(less, greater, p, type(p))
                
                return fast_sort(less) + [p] + fast_sort(greater)
            
            strs = [str(num) for num in nums]
            res = fast_sort(strs)
            return ''.join(res)
    

    内置函数方式

    class cmpSmaller(str):
        def __lt__(self, y):
            return self + y < y + self  # 字符串拼接比较(两两比较)
        # 按由小到大来排列
    
    class Solution:
        def minNumber(self, nums):
            res=sorted(map(str, nums),key=cmpSmaller)
            smallest = ''.join(res)
            return smallest
    

    sort 是只可比较 list 类型;sorted 可比较所有可迭代对象

    附加说明

    快排方式,无需多言。内置函数,实可深究。

    内置函数方式自定义了一个类 comSmaller 继承了 str 类。并且重写了其 __lt__方法。这个方法就是当程序使用 < 比较时,程序内部调用的方法。具体解析可点此了解

    现在我们来看一下这个 sorted 是怎么运行的。点此了解

    官方文档是这么说的:
    key 形参的值应该是一个函数,它接受一个参数并并返回一个用于排序的键。这种技巧速度很快,因为对于每个输入记录只会调用一次 key 函数。

    也就是说,当我们指定 keycmpSmaller 时,即 key 此时就是类 cmpSmaller 的别名。此时,在 sorted 内部,每一个待排序的字符串,被 key(strs中的字符串) 给重写了 __lt__ 方法。

    key 返回用于排序的键,也即是这个重写了 __lt__ 的字符串, 此时,sorted 对其待排序内容时,调用 <> 时,会自动调用这个重写的 __lt__ 方法。
    即使用了我们上面分析时自定义的字符串比较规则。从而可以得到按照自定义指定规则从小到大排序好的字符串列表。

  • 相关阅读:
    [CareerCup][Google Interview] Merge Two BST
    [面试] 全排列(非递归)
    [CareerCup][Google Interview] 打印最长序列
    [CareerCup][Google Interview] 实现一个具有get_min的Queue
    [LeetCode] Count and Say
    [LeetCode] Decode Ways
    定期向企业内部员工介绍企业当前的业务状况及未来的发展方向
    基础数据的来源的统一
    项目管理之代码合并
    年初离职潮的思考
  • 原文地址:https://www.cnblogs.com/yezigege/p/13397889.html
Copyright © 2011-2022 走看看