边工作边刷题:70天一遍leetcode: day 25-3
Burst Balloons
要点:利用了divide and conquer的方法,开始不是那么容易想出来,因为左右并不是完全分开的。这题的理解点在于把分割点想成在范围(left,right)最后一个burst的气球,因为left和right是exclusive的,那么这个气球带来的价值就是nums[k]nums[left]nums[right] (也就是只依赖于其边界)。其左边(left,k)和右边(k,right)仍然依赖k,但不会超过边界。这样就把问题分割了。
错误点:
- 注意dp的顺序:不能用外循环left,内循环right的方法,因为(left,k)或者(k,right)还没有更新到正确的值。因为(left,k)最终值不止left固定得到的临时值。所以循环应该基于长度len,从2开始直到n,然后left作为内循环,right就固定。
- 注意这种循环方式longest palindromic subsequence也用到,但是这题外循环left,内循环right的方法也能用。不同点在于这里没有k的第三重循环,只依赖于左右边界相邻的dp值
class Solution(object):
def maxCoins(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
def helper(nums, left, right, dp):
# print "left=",left,"right=",right
if dp[left][right]:
return dp[left][right]
if right-left<=1:
return 0 # error 1: not return 1, return 0
if right-left==2:
dp[left][right]=nums[left]*nums[right]*nums[left+1]
return dp[left][right]
dp[left][right]=0
for k in xrange(left+1, right):
lv = helper(nums, left, k, dp)
rv = helper(nums, k, right, dp)
#print "left=",left,"right=",right,"k=",k,lv,rv
dp[left][right]=max(dp[left][right], lv+rv+nums[left]*nums[k]*nums[right]) # error 2: not lv*rv*nums[k]
return dp[left][right]
nums = [1]+nums+[1]
dp = [[None for i in xrange(len(nums))] for j in xrange(len(nums))]
# print nums
return helper(nums, 0, len(nums)-1, dp)