zoukankan      html  css  js  c++  java
  • LeetCode-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:
    (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
    

    Credits:
    Special thanks to @dietpepsi for adding this problem and creating all test cases.

    Analysis:

    From: https://discuss.leetcode.com/topic/30746/share-some-analysis-and-explanations

    Be Naive First

    When I first get this problem, it is far from dynamic programming to me. I started with the most naive idea the backtracking.

    We have n balloons to burst, which mean we have n steps in the game. In the i th step we have n-i balloons to burst, i = 0~n-1. Therefore we are looking at an algorithm of O(n!). Well, it is slow, probably works for n < 12 only.

    Of course this is not the point to implement it. We need to identify the redundant works we did in it and try to optimize.

    Well, we can find that for any balloons left the maxCoins does not depends on the balloons already bursted. This indicate that we can use memorization (top down) or dynamic programming (bottom up) for all the cases from small numbers of balloon until n balloons. How many cases are there? For k balloons there are C(n, k) cases and for each case it need to scan the k balloons to compare. The sum is quite big still. It is better than O(n!) but worse than O(2^n).

    Better idea

    We then think can we apply the divide and conquer technique? After all there seems to be many self similar sub problems from the previous analysis.

    Well, the nature way to divide the problem is burst one balloon and separate the balloons into 2 sub sections one on the left and one one the right. However, in this problem the left and right become adjacent and have effects on the maxCoins in the future.

    Then another interesting idea come up. Which is quite often seen in dp problem analysis. That is reverse thinking. Like I said the coins you get for a balloon does not depend on the balloons already burst. Therefore
    instead of divide the problem by the first balloon to burst, we divide the problem by the last balloon to burst.

    Why is that? Because only the first and last balloons we are sure of their adjacent balloons before hand!

    For the first we have nums[i-1]*nums[i]*nums[i+1] for the last we have nums[-1]*nums[i]*nums[n].

    OK. Think about n balloons if i is the last one to burst, what now?

    We can see that the balloons is again separated into 2 sections. But this time since the balloon i is the last balloon of all to burst, the left and right section now has well defined boundary and do not affect each other! Therefore we can do either recursive method with memoization or dp.

    Final

    Here comes the final solutions. Note that we put 2 balloons with 1 as boundaries and also burst all the zero balloons in the first round since they won't give any coins.
    The algorithm runs in O(n^3) which can be easily seen from the 3 loops in dp solution.

    NOTE:

    we define dp[left][right] as the max coins we can get to burst the balloons BETWEEN left and right, NOT include left and right. Then, we have

    dp[left][right] = max(dp[left][last] + dp[last][right] + nums[left]*nums[last]*nums[right]) where left < last < right.

    Remember left and right will not be burst, that is why the last burst gets coins of nums[left]*nums[last]*nums[right].

    This is also the reason that we sum up dp[left][last] and dp[last][right]: the last balloon is not burst for dp[left][last] and dp[last][right].

    Solution:

    public class Solution {
        public int maxCoins(int[] inNums) {
            int[] nums = new int[inNums.length + 2];
            int len = 1;
            for (int i = 0; i < inNums.length; i++)
                if (inNums[i] > 0) {
                    nums[len++] = inNums[i];
                }
            nums[0] = nums[len++] = 1;
    
            int[][] max = new int[len][len];
    
            for (int i = 3; i <= len; i++)
                for (int left = 0; left <= len - i; left++) {
                    int right = left + i - 1;
                    for (int last = left + 1; last < right; last++) {
                        max[left][right] = Math.max(max[left][right],
                                max[left][last] + max[last][right] + nums[left] * nums[last] * nums[right]);
                    }
                }
    
            return max[0][len - 1];
        }
    }
  • 相关阅读:
    Linux配置虚拟RAID阵列
    D-Bus错误 D-Bus setup failed: Connection "xxx" is not allowed to own the service "org.bluez" due to security policies in the configuration file
    ftp
    echarts图例过多,折线过多颜色不知道怎么分配怎么办??优化如下
    vuex页面刷新数据丢失的解决办法
    obj转换为gltf方法three.js一步一步来--性能优化超厉害的!!!!!超赞操作!!!Obj模型转Gltf模型并超强压缩!!!!!
    three.js一步一步来--加载模型并修改其大小、按照规定的区域把一堆模型摆得整整齐齐~~~
    three.js一步一步来--简单交互--点击物体变红
    线上代码已变更,客户没有刷新浏览器,导致点击菜单后找不到相对路由js文件无法加载XXX路由,解决办法如下
    angular配置多个系统 配置动态路由,缩短模块初次加载时间,快速打开界面,优化用户访问体验
  • 原文地址:https://www.cnblogs.com/lishiblog/p/5833065.html
Copyright © 2011-2022 走看看