解法
解法一:记忆化搜索
就是从上再下的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……)
最大
n=1
时,显然成立- 当
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} at−1和 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,at−1]/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,at−1])/[at,ak]
问题变成要证明在不同的t取值时,t=2
是最大的取值t=2
时,表达式为 a 1 [ a 2 , a k ] \frac{a_1}{[a_2,a_k]} [a2,ak]a1t>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,at−1]∗[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,at−1]∗[at,ak]a1×a1[a2,ak]=at∗∏i=tkai∏i=t+1kai=at∗at1≤1,所以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:])))