leetcode 312. Burst Balloons
来源:互联网 发布:linux 中文方格 编辑:程序博客网 时间:2024/06/06 09:35
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:
(1) You may imagine nums[-1] = nums[n] = 1
. They are not real therefore you can not burst them.
(2) 0 ≤ n
≤ 500, 0 ≤ nums[i]
≤ 100
Example:
Given [3, 1, 5, 8]
Return 167
nums = [3,1,5,8] --> [3,5,8] --> [3,8] --> [8] --> [] coins = 3*1*5 + 3*5*8 + 1*3*8 + 1*8*1 = 167
我们假设在 [left,right] 区间内索引为 i 的气球被最后戳破,那么maxcoins(left,right) =nums[left-1]*nums[i]*nums[right+1] + maxcoins(left,i-1) +maxcoins(i+1,right).
以 [3,2,5,8] 为例子吧,假设2被最后戳破,那么maxcoins(0,3)=1*2*1 + maxcoins(0,0) +maxcoins(2,3),
因为最后戳破的是2,那么最后2左右已经没有气球了,所以最终的那次乘积只有2乘以(索引为-1的元素)乘以(索引为n的元素)。
然后递归地看2左边的元素区间[3]:maxcoins(0,0)=nums[0]*nums[left-1]*nums[right+1]+0+0=1*3*2=6,此时left-1指索引为-1的元素,right+1就是指2了。“+0+0"是因为更进一步的递归已经使right<left了,所以返回0
然后递归地看2右边的元素区间[5,8]:再假设该区间内5是最后被戳破的,它的left-1和right+1分别是2和1。我们可以想象8先被戳破之后,5左边是2,右边就变成了1,符合逻辑。......再假设该区间内8是最后被戳破的,它的left-1和right+1分别是2和1。我们可以想象5先被戳破之后,8左边变成了2,右边是1,也符合逻辑。
另外,这道题需要在递归时保存一个记忆数组memory[left][right]来记忆index为[left,right]的区间内maxCoins值,不然递归中会有多次重复计算[left,right]区间的最大硬币数,会TLE。
package leetcode;public class Burst_Balloons_312 {public int maxCoins(int[] nums) {int[][] memory=new int[nums.length][nums.length];return maxCoins(nums,0,nums.length-1,memory);}public int maxCoins(int[] nums,int left,int right,int[][] memory){if(left>right){return 0;}if(memory[left][right]>0){return memory[left][right];}int maxCoins=0;for(int i=left;i<=right;i++){int coins=getValue(nums, left-1)*getValue(nums, i)*getValue(nums, right+1)+maxCoins(nums,left,i-1,memory)+maxCoins(nums, i+1, right,memory);if(coins>maxCoins){maxCoins=coins;}}memory[left][right]=maxCoins;return maxCoins;}public int getValue(int[] nums,int index){if(index==-1||index==nums.length){return 1;}else{return nums[index];}}public static void main(String[] args) {// TODO Auto-generated method stubBurst_Balloons_312 b=new Burst_Balloons_312();int[] nums=new int[]{8,2,6,8,9,8,1,4,1,5,3,0,7,7,0,4,2,2};System.out.println(b.maxCoins(nums));}}
这道题还可以用DP来代替递归。dp[i][j] 来存储 index为i~j 的区间内的最大硬币数。那么我们需要的结果就是dp[0][nums.length - 1].
这道题的DP,并不是跟以前一样 i和j从小到大来填充,大的i、j 值通过 小的i、j值算出来填充。这道题这样想的话就会没有解决办法。
思路是从 j-i 的范围从小到大来填充。一开始考虑i=j的情形,填充。再考虑j-i=1的情形,填充。......慢慢把范围扩大,最后扩大成 j-i=nums.length - 1来填充,这就是我们要的结果。
即 [ ][ ][ ][ ][ ][ ]
=> [ ][ ][ ]
=> [ ][ ]
=> [ ]
因为在求解left~right的maxcoins过程中,假设当前最后被戳破的是i,那么之后要递归求解(left,i-1)和(i+1,right)的情况,也就是说要用到范围更小的区间。所以范围更小的区间需要先被求出来。
哈哈,要是还看不懂的就看看别人的英文原版解释吧。
The basic idea is that we can find the maximal coins of a subrange by trying every possible final burst within that range. Final burst means that we should burst balloon i as the very last one and burst all the other balloons in whatever order. dp[i][j] means the maximal coins for range [i...j]. In this case, our final answer is dp[0][nums.length - 1].
When finding the maximal coins within a range [start...end], since balloon i is the last one to burst, we know that in previous steps we have already got maximal coins of range[start .. i - 1] and range[i + 1 .. start], and the last step is to burst ballon i and get the product of balloon to the left of i, balloon i, and ballon to the right of i. In this case, balloon to the left/right of i is balloon start - 1 and balloon end + 1.
In my opinion, subrange will be used by a larger range when we're trying for every possible final burst. It will be like [larger start.....start - 1, [start .. end] end + 1/ larger end], when final burst is at index start - 1, the result of this sub range will be used, and at this moment, start - 1 will be there because it's the final burst and end + 1 will also be there because is out of range. Then we can guarantee start - 1 and end + 1 will be there as adjacent balloons of balloon i for coins.
public int maxCoins(int[] nums) {if (nums == null || nums.length == 0)return 0;int[][] dp = new int[nums.length][nums.length];for (int len = 0; len < nums.length; len++) {for (int start = 0; start < nums.length - len; start++) {int end = start + len;for (int i = start; i <= end; i++) {int coins = nums[i] * getValue(nums, start - 1) * getValue(nums, end + 1);if (i != start) {coins += dp[start][i - 1];// If not first one, we can// add subrange on its left.}if (i != end) {coins += dp[i + 1][end];// If not last one, we can add// subrange on its right}dp[start][end] = Math.max(dp[start][end], coins);}}}return dp[0][nums.length - 1];}private int getValue(int[] nums, int i) { // Deal with num[-1] and// num[num.length]if (i < 0 || i >= nums.length) {return 1;}return nums[i];}
- leetcode 312. Burst Balloons
- [leetcode] 312. Burst Balloons
- LeetCode 312. Burst Balloons
- LeetCode 312. Burst Balloons
- leetcode.312. Burst Balloons
- 【leetcode】312. Burst Balloons
- LeetCode 312. Burst Balloons
- leetcode 312. Burst Balloons
- leetcode 312.Burst Balloons
- Leetcode-312. Burst Balloons
- 【Leetcode】312. Burst Balloons
- 【leetcode】312. Burst Balloons
- 【leetcode】312. Burst Balloons
- LeetCode 312. Burst Balloons
- 【Leetcode】312. Burst Balloons
- 【LeetCode】312. Burst Balloons
- 【LeetCode】312. Burst Balloons
- leetcode 312. Burst Balloons
- 51Nod-消灭兔子-(优先队列)
- struts.xml配置详解
- touch命令
- 网络基本概念之TCP, UDP, 单播(Unicast), 多播(组播)(Multicast)
- arp协议
- leetcode 312. Burst Balloons
- 《Spring Cloud Netflix》-- 服务注册和服务发现-Eureka的服务认证和集群
- ES6箭头函数
- LIS最长上升子序列三种方法
- Python2.7 如何引入自己写的类
- linux-fedora系统下搭建本地owncloud网盘
- 以太网数据格式与封装解封
- oracle学习之bulk collect用法(转)
- 使用Aria2下载百度网盘和115的资源