Burst Balloons
Given n
balloons, indexed from 0
to n-1
. Each balloon is painted with a number on it represented by array nums
. You are asked to burst all the balloons. If the you burst balloon i you will get nums[left] * nums[i] * nums[right]
coins. Here left
and right
are adjacent indices of i
. After the burst, the left
and right
then becomes adjacent.
Find the maximum coins you can collect by bursting the balloons wisely.
Note:
You may imagine
nums[-1] = nums[n] = 1
. They are not real therefore you can not burst them.0 ≤
n
≤ 500, 0 ≤nums[i]
≤ 100
Example:
Analysis
A very nice analysis on LeetCode talking about several approaches from brute-force to divide and conquer as well as dynamic programming:
https://leetcode.com/problems/burst-balloons/discuss/76228/Share-some-analysis-and-explanations
一、利用分治法Divide and Conquer结合记忆化memoization
二、或者利用区间型动态规划Dynamic Programming
Divide and Conquer with Memoization
https://mnmunknown.gitbooks.io/algorithm-notes/625,_dong_tai_gui_hua_ff0c_qu_jian_lei_dp.html
https://leetcode.com/problems/burst-balloons/discuss/76245/Easiest-Java-Solution
subproblems are overlapped, so we can use divide and conquer + cache
Balloons
0, 1, ..., n - 1
What is the max value if we burst all of them
[0, n - 1]
?Let's first consider bursting
[start, end]
(includingstart
andend
boundaries)Imagine index
i
as the last one in the interval to be bursted
[start, ... i - 1, (i), i + 1 ... end]
Before the end, we already bursted
[start, i - 1]
and[i + 1, end]
Before the end, boundaries
start - 1
,i
,end + 1
are always thereThis helps us calculate coins without worrying about details inside
[start, i - 1]
and[i + 1, end]
So the range can be divided into
start - 1
,maxCoin(start, i - 1)
,i
,maxCoins(i + 1, end)
,end + 1
基本思想就是在区间[start, end]
中循环i
,i
作为该区间内最后被爆的气球,这样区间被分成了左右两个区间,再依次递归地寻找 [start, i - 1]
和 [i + 1, end]
的区间。这样就变成了子问题,而子问题区间上是可能有重叠的,因此可以用memoization来优化递归。
Dynamic Programming
这题的难点在于,如何在动态变化的数组中,正确定义并计算subproblem.
因为数组一直在变化,如何计算每次打爆获得的coin呢?
是否可以将子问题定义为寻找(left, right)区间内能得到最多的coin数目?
难想到的是从最后被打爆的气球入手,这种情况下,区间的左右两个两个元素就是确定的,而改变(循环i
)区间内最后被打爆的气球则会得到不同的结果,从而找到最大
State:
dp[i][j]
表示 i 到 j 区间中,打爆所有气球的最大coin数目
Function:
对于所有k属于
{i,j}
, 表示第k号气球最后打爆。k
is the last balloon to burst.midValue = arr[i- 1] * arr[k] * arr[j + 1];
dp[i][j] = max(dp[i][k-1] + d[k+1][j] + midvalue)
Initialize:
for each
i
dp[i][i] = 0
Answer:
dp[0][n-1]
Solution
Divide & Conquer + Recursive + Memoization - Easy to Understand Solution (16 ms, faster than 14.04%)
https://leetcode.com/problems/burst-balloons/discuss/76245/Easiest-Java-Solution
start
, end
boundary included (boundaries will be burst)
[start, ... i - 1, (i), i + 1 ... end]
*(Favorite) - Same idea as above (Divide & Conquer with Memoization) but faster performance (6ms 87.86%)
Building a new array first for faster access, compared to above getVal()
function
Other answers for reference
*Divide and Conquer, Memoization, Recursive - (Runtime: 5 ms, faster than 99.18%)
(not including boundaries in the recursion - boundary balloons not bursted)
Dynamic Programming - 6 ms , faster than 88.28%
Reference
[区间类DP总结](https://www.jianshu.com/p/4c462077f8f2\
Last updated