[LeetCode解题报告] 312. 戳气球

这篇博客介绍了如何解决LeetCode中的312.戳气球问题。作者采用了逆向思考和记忆化搜索的方法,通过在数组两端添加虚拟节点1来处理边界情况,并详细分析了思路、时间复杂度和代码实现。动态规划也是解决此问题的一种选择。
摘要由CSDN通过智能技术生成

一、 题目

1. 题目描述

  1. 戳气球

难度:困难

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

现在要求你戳破所有的气球。戳破第 i 个气球,你可以获得 nums[i - 1] * nums[i] * nums[i + 1] 枚硬币。 这里的 i - 1i + 1 代表和 i 相邻的两个气球的序号。如果 i - 1i + 1 超出了数组的边界,那么就当它是一个数字为 1 的气球。

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

示例 1:

输入:nums = [3,1,5,8]
输出: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

示例 2:

输入:nums = [1,5]
输出:10

提示:

  • n == nums.length
  • 1 <= n <= 300
  • 0 <= nums[i] <= 100

2. 原题链接

链接: 312. 戳气球

二、 解题报告

1. 思路分析

  • 如果正向模拟思考,那每次戳破一个数组状态都发生变化,很难思考,不如我们逆向思考(这正好是记忆化搜索的思考方式)。

  • 在这之前我们在数组两边增加两个虚拟节点1,方便处理边界情况。

  • 遍历区间内每个气球作为最后一个戳破的气球:

    • 假设我们处理开区间(l,r)下标为i的气球,那这个i气球的贡献一定是nums[i]*nums[l]*nums[r],因为i是最后一个戳破的,它一定和数组的边界进行计算。
    • 那么这时它再加上左、右区间的戳破最大值,就是这个区间总共的值。
    • 而左右区间明显是子问题:
    • 左区间(l,i);右区间(i,r)
  • 具体实现时:

    • 如果开区间边界l+1<=r,显然结果是0
    • 否则遍历每个i对ret进行更新。

2. 复杂度分析

最坏时间复杂度O(n3)

  • n是节点数。
  • 一共n2个区间,全都遍历到了,每个区间遍历了n次。

3. 代码实现

记忆化搜索

class Solution:
    def maxCoins(self, nums: List[int]) -> int:
        nums = [1] + nums + [1]
        @cache
        def dfs(l,r):
            ret = 0
            for i in range(l+1,r):
                ret = max(ret, nums[l]*nums[r]*nums[i] + dfs(l,i) + dfs(i,r))
            return ret
        return dfs(0,len(nums)-1)

三、 本题小结

  1. 动态规划也能做,更快。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值