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

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成立,令数组为 a 1 , a 2 , . . . , a k a_1,a_2,...,a_k a1,a2,...,ak,令 [ a i , a j ] [a_i,a_j] [ai,aj]表示 a i / a i + 1 / . . . / a j a_i/a_{i+1}/.../a_j ai/ai+1/.../aj
    假设最后一步除法放在 a t − 1 a_{t-1} at1 a t a_t at之间。
    首先,由于n<k时规律成立,所以 [ a 1 , a t − 1 ] / a t / a t + 1 / . . . / a k [a_1,a_{t-1}]/a_t/a_{t+1}/.../a_k [a1,at1]/at/at+1/.../ak的最大值肯定是 ( a 1 / [ a 2 , a t − 1 ] ) / [ a t , a k ] (a_1/[a_2,a_{t-1}])/[a_t,a_k] (a1/[a2,at1])/[at,ak]
    问题变成要证明在不同的t取值时,t=2是最大的取值
    • t=2时,表达式为 a 1 [ a 2 , a k ] \frac{a_1}{[a_2,a_k]} [a2,ak]a1
    • t>2时,表达式为 a 1 [ a 2 , a t − 1 ] ∗ [ a t , a k ] \frac{a_1}{[a_2,a_{t-1}]*[a_t,a_k]} [a2,at1][at,ak]a1
      将两者作商: a 1 [ a 2 , a t − 1 ] ∗ [ a t , a k ] × [ a 2 , a k ] a 1 = ∏ i = t + 1 k a i a t ∗ ∏ i = t k a i = 1 a t ∗ a t ≤ 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:])))
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值