【Leetcode】553. Optimal Division 553. 最优除法

本文探讨了如何从一组整数中找到能产生最大结果的除法链,并提供了两种解法。一是使用记忆化搜索的动态规划方法,二是通过数学证明得出的直接解法。直接解法证明了在所有可能的除法链中,特定形式的链总能产生最大结果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1

解法

解法一:记忆化搜索

就是从上再下的DP

class Solution(object):
    def optimalDivision(self, nums):
        """
        :type nums: List[int]
        :rtype: str
        """
        n = len(nums)
        mem = {}
        split = {}
        def solve(i,j,ismax):
            if (i,j,ismax) not in mem:
                if j-i==1:
                    return nums[i]
                res = None
                s = None
                for k in xrange(i+1,j):
                    if ismax:
                        t = 1.0*solve(i,k,True)/solve(k,j,False)
                        if res == None or res<t:
                            res = t
                            s = k
                    else:
                        t = 1.0*solve(i,k,False)/solve(k,j,True)
                        if res == None or res>t:
                            res = t
                            s = k
                mem[(i,j,ismax)] = res
                split[(i,j,ismax)] = s
            return mem[(i,j,ismax)]
        solve(0,n,True)
        def GetAns(i,j,ismax):
            if j-i==1:
                return str(nums[i])
            k = split[(i,j,ismax)]
            return "%s/%s" % (GetAns(i,k,ismax),nums[k] if k==j-1 else "(%s)" % GetAns(k,j,not ismax))
        return GetAns(0,n,True)

解法二:数学

可以证明,给a/b/c/d/……加括号,永远是a/(b/c/d……)最大

  1. n=1时,显然成立
  2. n<k成立,令数组为a1,a2,...,aka_1,a_2,...,a_ka1,a2,...,ak,令[ai,aj][a_i,a_j][ai,aj]表示ai/ai+1/.../aja_i/a_{i+1}/.../a_jai/ai+1/.../aj
    假设最后一步除法放在at−1a_{t-1}at1ata_tat之间。
    首先,由于n<k时规律成立,所以[a1,at−1]/at/at+1/.../ak[a_1,a_{t-1}]/a_t/a_{t+1}/.../a_k[a1,at1]/at/at+1/.../ak的最大值肯定是(a1/[a2,at−1])/[at,ak](a_1/[a_2,a_{t-1}])/[a_t,a_k](a1/[a2,at1])/[at,ak]
    问题变成要证明在不同的t取值时,t=2是最大的取值
    • t=2时,表达式为a1[a2,ak]\frac{a_1}{[a_2,a_k]}[a2,ak]a1
    • t>2时,表达式为a1[a2,at−1]∗[at,ak]\frac{a_1}{[a_2,a_{t-1}]*[a_t,a_k]}[a2,at1][at,ak]a1
      将两者作商:a1[a2,at−1]∗[at,ak]×[a2,ak]a1=∏i=t+1kaiat∗∏i=tkai=1at∗at≤1\frac{a_1}{[a_2,a_{t-1}]*[a_t,a_k]}\times\frac{[a_2,a_k]}{a_1}=\frac{\prod_{i=t+1}^ka_i}{a_t*\prod_{i=t}^ka_i}=\frac{1}{a_t*a_t}\le 1[a2,at1][at,ak]a1×a1[a2,ak]=ati=tkaii=t+1kai=atat11,所以t=2时是最大,得证。
class Solution(object):
    def optimalDivision(self, nums):
        """
        :type nums: List[int]
        :rtype: str
        """
        n = len(nums)
        if n<=2:
            return "/".join(map(str,nums))
        return "%d/(%s)" % (nums[0],"/".join(map(str,nums[1:])))
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值