牛客网在线编程专题《剑指offer-面试题33》把数组排成最小的数

我的个人微信公众号:Microstrong

微信公众号ID:MicrostrongAI

微信公众号介绍:Microstrong(小强)同学主要研究机器学习、深度学习、计算机视觉、智能对话系统相关内容,分享在学习过程中的读书笔记!期待您的关注,欢迎一起学习交流进步!

知乎主页:https://www.zhihu.com/people/MicrostrongAI/activities

Github:https://github.com/Microstrong0305

个人博客:https://blog.csdn.net/program_developer

题目链接:

https://www.nowcoder.com/practice/8fecd3f8ba334add803bf2a06af1b993?tpId=13&tqId=11185&tPage=2&rp=2&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking

题目描述:

解题思路: 

(1)重新定义排序规则,时间复杂度O(nlogn)

      这个题目最直接的做法应该是先求出这个数组中所有数字的全排列,然后把每个排列拼起来,最后求出拼起来的数字的最大值。求数组的排列和面试题 28 “字符串的排列”非常类似,这里不再详细介绍。根据排列组合的知识,n个数字总共有n!个排列。我们再来看一种更快的算法。

      这道题其实是希望我们能找到一个排序规则,数组根据这个规则排序之后能排成一个最小的数字。要确定排序规则,就要比较两个数字,也就是给出两个数字m和n, 我们需要确定一个规则判断m和n哪个应该排在前面,而不是仅仅比较这两个数字的值哪个更大。

      根据题目的要求,两个数字m和n能拼接成数字mn和nm。 如果mn<nm, 那么我们应该打印出mn, 也就是m应该排在n的前面,我们定义此时m小于n;反之,如果nm<mn,我们定义n小于m。如果mn=nm,m等于n。在下文中,符号 “<”、“>” 及 “=” 表示常规意义的数值的大小关系,而文字 “大于”、“ 小于”、“等于” 表示我们新定义的大小关系。

      接下来考虑怎么去拼接数字,即给出数字m和n,怎么得到数字mn和nm并比较它们的大小。直接用数值去计算不难办到,但需要考虑到一个潜在的问题就是m和n都在int能表达的范围内,但把它们拼起来的数字mn和nm用int表示就有可能溢出了,所以这还是一个隐形的大数问题 。

      一个非常直观的解决大数问题的方法就是把数字转换成字符串。另外,由于把数字m和n拼接起来得到mn和nm,它们的位数肯定是相同的,因此比较它们的大小只需要按照字符串大小的比较规则就可以了。

      基于以上思路,我们可以写出如下代码。

已经AC的代码:

from functools import cmp_to_key


class Solution:

    def PrintMinNumber(self, numbers):
        def cmp(a, b):
            num1 = str(a) + str(b)
            num2 = str(b) + str(a)
            if num1 < num2:
                return -1
            elif num1 > num2:
                return 1
            else:
                return 0

        if numbers is None or len(numbers) == 0:
            return ""

        numbers.sort(key=cmp_to_key(cmp))
        # sorted(numbers, key = cmp_to_key(cmp))
        return "".join(str(num) for num in numbers)


if __name__ == "__main__":
    sol = Solution()
    numbers = [3, 32, 321]
    print(sol.PrintMinNumber1(numbers))

(2)使用冒泡排序

# -*- coding:utf-8 -*-

class Solution:

    # 使用冒泡排序
    def PrintMinNumber2(self, numbers):
        if numbers == None or len(numbers) <= 0:
            return ""

        # strNum = [str(num) for num in numbers]
        strNum = list(map(str, numbers))

        for i in range(len(numbers) - 1):
            for j in range(i + 1, len(numbers)):
                if strNum[i] + strNum[j] > strNum[j] + strNum[i]:
                    strNum[i], strNum[j] = strNum[j], strNum[i]

        return ''.join(strNum)


if __name__ == "__main__":
    sol = Solution()
    numbers = [3, 32, 321]
    print(sol.PrintMinNumber2(numbers))

Reference:

【1】《剑指offer》,何海涛著。

【2】 https://github.com/Jack-Lee-Hiter/AlgorithmsByPython/blob/master/Target%20Offer/%E6%8A%8A%E6%95%B0%E7%BB%84%E6%8E%92%E6%88%90%E6%9C%80%E5%B0%8F%E7%9A%84%E6%95%B0.py#L16

【3】 https://blog.csdn.net/yurenguowang/article/details/80568996

【4】 https://blog.csdn.net/u013129109/article/details/80089387

【5】 https://github.com/shenweichen/coding_interviews/blob/master/45.%E6%8A%8A%E6%95%B0%E7%BB%84%E6%8E%92%E6%88%90%E6%9C%80%E5%B0%8F%E7%9A%84%E6%95%B0/45.%E6%8A%8A%E6%95%B0%E7%BB%84%E6%8E%92%E6%88%90%E6%9C%80%E5%B0%8F%E7%9A%84%E6%95%B0.py

发布了285 篇原创文章 · 获赞 892 · 访问量 111万+

猜你喜欢

转载自blog.csdn.net/program_developer/article/details/103990265