戳气球题解

戳气球

1. 题目描述

有 n 个气球,编号为0 到 n-1,每个气球上都标有一个数字,这些数字存在数组 nums 中。

现在要求你戳破所有的气球。每当你戳破一个气球 i 时,你可以获得 nums[left] * nums[i] * nums[right] 个硬币。 这里的 left 和 right 代表和 i 相邻的两个气球的序号。注意当你戳破了气球 i 后,气球 left 和气球 right 就变成了相邻的气球。

求所能获得硬币的最大数量。[1]

你可以假设 nums[-1] = nums[n] = 1,但注意它们不是真实存在的所以并不能被戳破。
0 ≤ n ≤ 500, 0 ≤ nums[i]100

问题分析

1.刚看题时,这道题确实比较难入手,不过按照一般的思路来,还是可以想到动态规划的。面对这样的问题,我们首先将问题抽象化:题目中戳破气球可表示为从数组中的某个下标找一位数。我们可以设一个包含戳完气球的数组下标的数组:checked=[];那么每从nums选一个数,就将相应的下标push到checked数组里面,直到选完所有的数为止。则,问题就转换成关于nums下标的排列组合,这个时候就可以联想到暴力枚举的方法。那么相应的时间复杂度为O(n!),而题中n的范围在0-500之间,可想而知,这种方法在这里是行不通的。那么就得另辟蹊径了。

2.动态规划的分治思想:动态规划的一般思想是将问题分成若干个子问题,找到父子问题之间的状态转移方程。对于不经常运用算法的人来说,立刻想到是有些困难的,那么如何去找状态转移方程呢??
我认为有以下几个要点:
其一,注意问题的可拆分性,题目中的问题可以表达成多个子问题。
其二,不可后向影响性,前一个问题的解不能依赖于后一个问题的解。
其三,可递归性。
当一个问题符合以上三种时,基本上可以运用动态规划来解决。我们以这个问题为例进行分析:
题目让我们求戳破所有气球可获得的最大硬币数,而气球则是数组下标表示,数组里面的内容则是具体的数。那么我们可以将这个数组表示为一个区间[0,nums.length-1],即在此区间戳破气球所能获得的最大硬币数,而根据题目所获得的硬币数表示为:nums[left]*nums[i]*nums[right],那么我们试着分析它的可拆分性,区间[i,j]之间的最大获得硬币数是多少??我们采用数学上常用的归纳法来进行分析:

假设nums是一个元素数组:则获得的最大硬币数为1*nums[0]*1;

假设nums是包含两个元素的数组:则获得的最大硬币数为:[0,1]:MAX(1*nums[0]*nums[1]+1*nums[1]*1,nums[0]*nums[1]*1+1*nums[0]*1);

假设nums是包含三个元素的数组:则获得的最大硬币数为:
[0,2]:MAX(1*nums[0]*nums[1]+1*nums[1]*nums[2]+1*nums[2]*1  ,  1*nums[0]*nums[1]+nums[1]*nums[2]*1+1*nums[1]*1  ,  nums[0]*nums[1]*nums[2]+1*nums[0]*nums[2]+1*nums[2]*1 , nums[0]*nums[1]*nums[2]+nums[0]*nums[2]*1+1*nums[0]*1,
nums[1]*nums[2]*1+nums[0]*nums[1]*1+1*nums[0]*1,
nums[1]*nums[2]*1+1*nums[1]*nums[2]+1*nums[0]*1,
...
);

可知[i,j]=[i,c]+[c,j]+nums[i]*nums[c]*nums[j];

解题

var maxCoins = function(nums) {
    nums.unshift(1);
    nums.push(1);
    var dp=[];

    for(var i=0;i<nums.length;i++){
        var tmp=[];
        for(var j=0;j<nums.length;j++){
            tmp[j]=0;
        }
        dp[i]=tmp;
    }

    for(var i=2;i<nums.length;i++){

        for(var j=0;j<nums.length;j++){
            var n=i+j;

            if(n<nums.length){
                for(var c=j+1;c<n;c++){
                    dp[j][n]=Math.max(dp[j][n],nums[j]*nums[c]*nums[n]+dp[j][c]+dp[c][n]);
                }
            }
        }
    }

    return dp[0][nums.length-1];
};

题目来源

  1. https://leetcode-cn.com/problems/burst-balloons
发布了10 篇原创文章 · 获赞 0 · 访问量 577

猜你喜欢

转载自blog.csdn.net/wweTHEUT/article/details/103725839