Leetcode-贪心法-把数组排成最小的数

面试题45. 把数组排成最小的数

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

示例 1:

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

证明过程:

  • 当只有一个元素时,即 Input = [A]时,则最小数为A

  • 当存在两个元素时,即 Input=[A,B]时,则最小数为 min([int(str(A)+str(B)),int(str(B)+str(A))])

  • 当超过两个元素时,设后面字母都代表数字对应的字符串,设最小数为ABCDE,

    (1)若int(BA)小于int(AB),则最小数应该为BACDE,矛盾,同理可得,相邻两个变量之间有int(前面的变量 + 后面的变量) < int(后面的变量+ 前面的变量)的关系

    (2)此时,证明无论相隔多远,都有在最小数字符串中都有int(前面的变量 + 后面的变量) < int(后面的变量+ 前面的变量)的关系。

    具体地,当最小句子为LOPATYUBCVN时,,则该句子可变为YAXBZ,其中Y,X,Z为其他字母合成的表示符,其中Y=LOP,X=TYU,Z=CVN,固定Y,X,Z的组合。设其A,X,B,Y,Z的长度分别为a, x, b, y, z。

    则根据(1)有,通过A,B的邻居X建立A和B的关系

    i n t ( A X B Z ) ≤ i n t ( X A B Z ) → A × 1 0 x + b + z + X × 1 0 b + z + B × 1 0 z + Z ≤ X × 1 0 a + b + z + A × 1 0 b + z + B × 1 0 z + Z → A × 1 0 x + X ≤ X × 1 0 a + A → A × ( 1 0 x − 1 ) ≤ X × ( 1 0 a − 1 ) → A × 1 0 x − 1 1 0 a − 1 ≤ X int(AXBZ)\leq int(XABZ) \newline \rightarrow A \times 10^{x+b+z} +X\times10^{b+z}+B\times10^z+Z\leq X \times 10^{a+b+z}+A\times10^{b+z}+B\times10^z+Z \newline \rightarrow \mathbf{A \times 10^x +X \leq X \times 10^a+A} \newline\rightarrow \mathbf{A\times(10^x-1) \leq X\times(10^a-1)}\newline \rightarrow \textcolor{red}{\mathbf{A\times \frac{10^x-1}{10^a-1} \leq X}} int(AXBZ)int(XABZ)A×10x+b+z+X×10b+z+B×10z+ZX×10a+b+z+A×10b+z+B×10z+ZA×10x+XX×10a+AA×(10x1)X×(10a1)A×10a110x1X

    扫描二维码关注公众号,回复: 15508669 查看本文章

    i n t ( X B Z ) ≤ i n t ( B X Z ) → X × 1 0 b + z + B × 1 0 z + Z ≤ B × 1 0 x + z + X × 1 0 z + Z → X × 1 0 b + B ≤ B × 1 0 x + X → X ≤ B ×   1 0 x − 1 1 0 b − 1 int(XBZ)\leq int(BXZ) \newline \rightarrow X \times 10^{b+z} +B\times10^{z} + Z \leq B \times 10^{x+z}+X\times10^{z}+Z \newline \rightarrow \mathbf{X \times 10^b +B \leq B \times 10^x+X}\newline\rightarrow \textcolor{red}{\mathbf{X \leq B\times\ \frac{10^x-1}{10^b-1}}} int(XBZ)int(BXZ)X×10b+z+B×10z+ZB×10x+z+X×10z+ZX×10b+BB×10x+XXB× 10b110x1

    从而有, A × 1 0 x − 1 1 0 a − 1 ≤ X ≤ B × 1 0 x − 1 1 0 b − 1 \mathbf{A\times\frac{10^x-1}{10^a-1}\leq X \leq B\times \frac{10^x-1}{10^b-1}} A×10a110x1XB×10b110x1

    即, A × 1 0 b + B ≤ B × 1 0 a + A → i n t ( A B ) ≤ i n t ( B A ) \textcolor{red}{\mathbf{A\times10^b+B\leq B \times 10^a +A\rightarrow int(AB)\leq int(BA)}} A×10b+BB×10a+Aint(AB)int(BA),特别地,当Y,Z为空字符串时,易证上式也成立。

    综上所述,对于构成最小数字的字符串而言,任意两个字母之间有int(previous+later) > int(later+previous) 的关系。

解决方案:

根据上述证明,我们知道形成最小数的字符串,两个字母之间存在int(previous+later) > int(later+previous) 的关系,则我们可以定义一种比较方法,其伪代码如下所示:

def cmp_function(A:int,B:int):
    """
		:params A 表示一个数字
	  :params B 表示一个数字
		:return True if A{<=}B else False
		"""
		return int(str(A)+str(B)) <= int(str(B)+str(A))

通过该比较方法,我们使用快速排序对原列表进行从小到大排序,便可得到构成最小数的列表顺序,其代码如下所示:

class Solution:
    def minNumber(self, nums: List[int]) -> str:
        # 快排排序
        def partition(nums,left,right):
            temp = nums[left]
            l,r = left,right
            while l < r:
                while not cmp_function(nums[r],temp) and l < r:
                        r-=1
                nums[l] = nums[r]
                while cmp_function(nums[l],temp) and l < r:
                        l+=1
                nums[r] = nums[l]
                r -= 1
            nums[l] = temp
            return l

        def quickSort(nums,left,right):
                if left >= right:
                        return
                mid = partition(nums,left,right)
                quickSort(nums,left,mid-1)
                quickSort(nums,mid+1,right)
                return
        quickSort(nums,0,len(nums)-1)
        return ''.join([str(item) for item in nums])

猜你喜欢

转载自blog.csdn.net/YmgmY/article/details/129239689