题目描述
有 n 个气球,编号为 0 到 n - 1,每个气球上都标有一个数字,这些数字存在数组 nums 中。
现在要求你戳破所有的气球。戳破第 i 个气球,你可以获得 nums[i - 1] * nums[i] * nums[i + 1] 枚硬币。这里的 i - 1 和 i + 1 代表和 i 相邻的两个气球的序号。如果 i - 1 或 i + 1 超出了数组的边界,那么就当它是一个数字为 1 的气球。
求所能获得硬币的最大数量。
示例
示例 1:
1 | 输入:nums = [3,1,5,8] |
示例 2:
1 | 输入:nums = [1,5] |
提示
n == nums.length1 <= n <= 3000 <= nums[i] <= 100
解题思路
这是一道经典的区间动态规划问题。
核心思想
本题使用逆向思维,从戳破最后一个气球开始考虑。
定义 dp[i][j] 表示:戳破开区间 (i, j) 之间所有气球能获得的最大硬币数(不包括 i 和 j)。
为了处理边界情况,我们在原数组两端各添加一个值为 1 的虚拟气球:
$$
\text{new_nums} = [1] + \text{nums} + [1]
$$
状态转移方程
假设最后戳破的是位置 k 的气球(i < k < j):
$$
dp[i][j] = \max_{i < k < j} { dp[i][k] + dp[k][j] + \text{new_nums}[i] \times \text{new_nums}[k] \times \text{new_nums}[j] }
$$
遍历顺序
- 区间长度
len从 2 开始递增到 n+1 - 计算每个区间
dp[i][j]的最大值
代码实现
1 | class Solution: |