每日一解 戳气球(困难的动归)

这是一篇关于LeetCode难题‘戳气球’的解析,涉及动态规划和分治策略。文章介绍了如何通过动态规划降低时间复杂度,避免重复计算,并给出了具体的解决方案和代码实现。
摘要由CSDN通过智能技术生成

题目 戳气球

有 n 个气球,编号为0 到 n-1,每个气球上都标有一个数字,这些数字存在数组 nums 中。
现在要求你戳破所有的气球。如果你戳破气球 i ,就可以获得 nums[left] * nums[i] * nums[right] 个硬币。 这里的 left 和 right 代表和 i 相邻的两个气球的序号。注意当你戳破了气球 i 后,气球 left 和气球 right 就变成了相邻的气球。
求所能获得硬币的最大数量。

说明:

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

示例:
输入: [3,1,5,8]
输出: 167
解释:
nums = [3,1,5,8] --> [3,5,8] --> [3,8] --> [8] --> []
coins = 315 + 358 + 138 + 181 = 167

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/burst-balloons

思路

我自己想了半天动归的思路,但是都没有什么结果。看了看官解才意识到居然是一道时间复杂度O(n3)的题目,确实是一道很困难的题目。想要得到状态转移方程,就需要想到采用分治法降低问题难度。例如想到将戳破气球反过来,改为依次添加气球,其实不算难事,但是要运用分治法的思路来看待添加气球的过程。也就是得到如下的方程:

F(left, right) = nums[left] * nums[middle] * nums[right] + F(left, middle) + F(middle, right)

其中,left是左端点,right是右端点,middle为中间将要添加进去的那个气球。
也就是问题可以通过分治思路得到一个正确的求解方向:添加一个气球进去,求一下左中右三个气球的乘积,再递归去考虑中气球与左边气球构成的左右端点,再加入气球会是什么结果,和中气球与右气球中间再次加入气球会是什么结果。一直递归到左右两个端点气球是相邻的了,那么这个时候没右气球可以插入了,就有:

F(left, right) = 0 (left >= right - 1)

这个时候大体方向的思路是有了,但是很明显时间复杂度不止O(n3),因为还没有采用动态规划的空间换时间,存储会被重复计算到的内容。这个时候就需要分析一下会被重复计算到的值是什么。
拿题目中举的例子,输入为[3,1,5,8]来进行计算:

序号 0 1 2 3 4 5
1 3 1 5 8 1
备注 左端点 右端点

这里参考了一下官解的思路,设置了值为1的左端点和右端点,方便再插入第一个元素的时候进行计算。按照我们之前反向回推,”插入“气球的思路来看,最初的序列是这样:

序号 0 5
1 1
备注 左端点 右端点

现在要处理的问题是从1——4的数字中选一个插入,那么依次来看一下情况:

序号 0 1 5
1 3 1
备注 左端点 右端点
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值