312. 戳气球
难度: 困难
有 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.length
1 <= n <= 500
0 <= nums[i] <= 100
自顶向下的动态规划
直接戳破气球会导致区间中间的元素不好处理,使用逆向思维,在区间中添加气球。
我们定义方法 $\textit{solve}$,令 $\textit{solve}(i,j)$ 表示将开区间 $(i,j)$ 内的位置全部填满气球能够得到的最多硬币数。由于是开区间,因此区间两端的气球的编号就是 $i$ 和 $j$,对应着 $\textit{val}[i]$ 和 $\textit{val}[j]$。
当 $i \geq j-1$ 时,开区间中没有气球,$\textit{solve}(i,j)$ 的值为 $0$;
当 $i < j-1$ 时,我们枚举开区间 $(i,j)$ 内的全部位置 $\textit{mid}$,令 $\textit{mid}$ 为当前区间第一个添加的气球,该操作能得到的硬币数为 $val[i]×val[mid]×val[j]$。
同时我们递归地计算分割出的两区间对 $\textit{solve}(i,j)$ 的贡献,这三项之和的最大值,即为 $\textit{solve}(i,j)$ 的值。这样问题就转化为求 $\textit{solve}(i,\textit{mid})$ 和 $\textit{solve}(\textit{mid},j)$ ,可以写出方程:
$\textit{solve}(i,j)= \begin{cases}{} \displaystyle \max_{\textit{mid} = i + 1}^{j - 1}val[i] \times \textit{val}[\textit{mid}] \times \textit{val}[j] + \textit{solve}(i, \textit{mid}) + \textit{solve}(\textit{mid}, j) ,&i < j - 1 \ 0, & i \geq j - 1 \end{cases}$
1 | 作者:LeetCode-Solution |
1 | class Solution { |
自底向上的动态规划
1 | class Solution { |