剑指offer[32 把数组排列成最小的数]

剑指offer[32 把数组排列成最小的数]

题目描述

输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323。

示例1

输入

[3,32,321]

返回值

"321323"
解决方法一:暴力求解

使用itertools.permutations生成全排列。然后找出全排列中的最小值。时间复杂度O(N!),空间复杂度O(N!),面试必挂率(99.99%)

import itertools
class Solution:
    def PrintMinNumber(self, numbers):
        # write code here
        if not numbers:
            return ""
        str_num = list(map(str, numbers))
        All_way = itertools.permutations(str_num)
        res = []
        for i in All_way:
            res.append(int(''.join(i)))
        return min(res)
解决方案二:排序

首先按照我的想法是,此题的比较优质的算法应该会使用到排序,但是如何制定排序规则?

先做个假设使用【1,32,3,321,5】,首先想到的是首位越小放在前面,则应该先将1放在最前面,5放在最后面。现在的话,仅对【32,3,321】如何进行排序更加好呢?比较完首位都是相同的,如何进行进一步的比较就是这道题的难点。

参考了lc上面的大神的思路:

https://leetcode-cn.com/problems/ba-shu-zu-pai-cheng-zui-xiao-de-shu-lcof/solution/mian-shi-ti-45-ba-shu-zu-pai-cheng-zui-xiao-de-s-4/

  • 若拼接字符串 x+y >y +x,则x "大于"y。
  • 反之,则x “小于” y。
  • 根据此规则对nums进行排序即可。
快速排序法:平均时间复杂度O(NlogN), 最差时间负杂度O(N^2)
class Solution:
    def minNumber(self, nums: List[int]) -> str:
        def quick_sort(l , r):
            if l >= r: return 
            i, j = l, r 
            while i < j:
                # 取最左边的数作为基准数,如果 str_i + base >= base + str_i,则可以判断i小于base 
                while strs[j] + strs[l] >= strs[l] + strs[j] and i < j: j -= 1
                while strs[i] + strs[l] <= strs[l] + strs[i] and i < j: i += 1
                strs[i], strs[j] = strs[j], strs[i]
            strs[i], strs[l] = strs[l], strs[i]
            quick_sort(l, i - 1)
            quick_sort(i + 1, r)
        
        strs = [str(num) for num in nums]
        quick_sort(0, len(strs) - 1)
        return ''.join(strs)
冒泡排序法:时间复杂度O(N^2)
class Solution:
    def minNumber(self, nums: List[int]) -> str:
        nums_str = [str(x) for x in nums]
        for i in range(len(nums_str)):
            for j in range(1,len(nums_str)-i):
                if nums_str[j] + nums_str[j-1] < nums_str[j-1] + nums_str[j]:
                    nums_str[j],nums_str[j-1] = nums_str[j-1],nums_str[j]
        return ''.join(nums_str)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值