My code:
public class Solution {
public int maxCoins(int[] nums) {
if (nums == null || nums.length == 0)
return 0;
int n = nums.length;
int[] help = new int[n + 2];
for (int i = 1; i < n + 1; i++)
help[i] = nums[i - 1];
help[0] = 1;
help[n + 1] = 1;
int[][] dp = new int[n + 2][n + 2];
for (int i = 0; i < n + 2; i++)
dp[i][i] = help[i];
for (int len = 2; len <= n + 1; len++) {
for (int i = 0; i <= n + 1 - len; i++) {
int j = i + len;
for (int k = i + 1; k < j; k++) {
dp[i][j] = Math.max(dp[i][j], help[i] * help[k] * help[j] + dp[i][k] + dp[k][j]);
}
}
}
return dp[0][n + 1];
}
}
这道题目看了答案后还是做了很久。
今天状态也很差。
具体看这篇文章把:
http://algobox.org/burst-balloons/
具体就是一种思路的转变。
假设[i...j]中以k,作为分割点。先破k。
那么 [i, k] and [k, j] 并不是互相独立的。因为他们之间还可以交际。
但是,如果假设,k是最后一个破裂的,那么, [i, k] and [k, j] 就是互相独立的了。
真的就是一个假设的转变,and everything changes.
记住这种reverse想法在DP中的应用。
Anyway, Good luck, Richardo!
首先说下,这道题目做了接近5个小时,最后给出的答案仍然超时,主要在于,思考的起点,还是不对的。
下面是正确的解法:
My code:
import java.util.HashMap;
public class Solution {
public int maxCoins(int[] nums) {
if (nums == null || nums.length == 0) {
return 0;
}
int[] bb = new int[nums.length + 2];
for (int i = 1; i < bb.length - 1; i++) {
bb[i] = nums[i - 1];
}
bb[0] = 1;
bb[bb.length - 1] = 1;
int n = bb.length;
int[][] cache = new int[n][n];
return helper(bb, cache, 0, n - 1);
}
private int helper(int[] bb, int[][] cache, int left, int right) {
if (left + 1 >= right) {
return 0;
}
else if (cache[left][right] != 0) {
return cache[left][right];
}
int ret = 0;
for (int i = left + 1; i < right; i++) {
ret = Math.max(ret, bb[left] * bb[i] * bb[right] + helper(bb, cache, left, i) + helper(bb, cache, i, right));
}
cache[left][right] = ret;
return ret;
}
}
reference:
https://discuss.leetcode.com/topic/30746/share-some-analysis-and-explanations
感觉想说的,上面的网页说的很清楚了。
他是 divide conquer + dp
最为重要的是,他把左右完全独立开来了。
这道题目太恶心,我不想多说什么,只是在问,有什么意义?
我的时间?
下面说下我的解法:
My code:
import java.util.HashMap;
public class Solution {
HashMap cache = new HashMap();
int total = 0;
int hit = 0;
public int maxCoins(int[] nums) {
if (nums == null || nums.length == 0) {
return 0;
}
boolean[] isVisited = new boolean[nums.length];
return helper(nums, isVisited);
}
private int helper(int[] nums, boolean[] isVisited) {
String hashcode = getHashcode(isVisited, nums);
if (cache.containsKey(hashcode)) {
return cache.get(hashcode);
}
int max = 0;
for (int i = 0; i < nums.length; i++) {
if (isVisited[i]) {
continue;
}
else {
isVisited[i] = true;
int coins = getCoin(isVisited, i, nums);
int ret = helper(nums, isVisited) + coins;
max = Math.max(max, ret);
isVisited[i] = false;
}
}
cache.put(hashcode, max);
return max;
}
private String getHashcode(boolean[] isVisited, int[] nums) {
StringBuilder hashcode = new StringBuilder();
for (int i = 0; i < isVisited.length; i++) {
if (!isVisited[i]) {
hashcode = hashcode.append("_" + nums[i]);
}
}
return hashcode.toString();
}
private int getCoin(boolean[] isVisited, int index, int[] nums) {
int left = index - 1;
int right = index + 1;
while (left >= 0) {
if (!isVisited[left]) {
break;
}
else {
left--;
}
}
while (right < isVisited.length) {
if (!isVisited[right]) {
break;
}
else {
right++;
}
}
int p1 = (left == -1 ? 1 : nums[left]);
int p2 = (right == isVisited.length ? 1 : nums[right]);
return p1 * nums[index] * p2;
}
public static void main(String[] args) {
Solution test = new Solution();
int[] nums = new int[]{8, 2, 6, 8, 9, 8, 1, 4, 1, 5, 3, 0, 7, 7, 0, 4, 2};
int ret = test.maxCoins(nums);
System.out.println(ret);
System.out.println("hit rate: " + test.hit / (test.total * 1.0));
}
}
是从上往下,但是对于某些已经计算过的情况,我会用cache。
比如
0 1 2 3 4
F F F F F
假设扎破了0
0 1 2 3 4
11 32 43 8 9
T F F F F
然后一直dfs,算出来他的最大值 m
然后我设计了一个hashcode 函数,计算 TFFFF的hashcode
即: _32_43_8_9
那么下次,我再碰到 _32_43_8_9 组合时,就直接拿结果就行了。
但这个解法仍然很恐怖的超时,应该速度快于 n! 但是 慢于 2^n
至于 上面的那个更好的解法,我不清楚他的算法复杂度是多少,但是真的很快!
题目,还是要坚持刷的!
简历上的那些软件,项目,也要全部准备好!
路,还很遥远。
你, 在哪里?
Anyway, Good luck, Richardo! -- 08/19/2016