【LeetCode】312. 戳气球

news2025/2/27 4:57:19

312. 戳气球(困难)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

解法一:动态规划

首先看一个区间:

在这里插入图片描述

区间(i,j) 是一个开区间,因为我们只能戳爆 i 和 j 之间的气球,不能戳爆索引为 i 和 j 的气球。

我们不妨考虑该区间内被戳爆的最后一个气球,索引记为 k。因为粉色气球是该区间内最后被戳爆的气球,所以在开区间 (i, j) 内除了它没有别的气球了,所以 DP 的状态转移方程只和 i 和 j 位置的数字有关。

在这里插入图片描述

状态定义

定义 dp[i][j] 表示 开区间 (i, j) 内能够得到的最多金币。

状态转移方程

开区间 (i, j) 内得到的最多金币分为三部分:

  • dp[i][k]:开区间 (i, k) 内得到的最多金币
  • nums[i] * nums[k] * nums[j] :戳爆气球 k 可以得到的金币数量
  • dp[k][j] :开区间 (k, j) 内得到的最多金币;

因此最终的状态转移方程为:dp[i][j] = dp[i][k] + nums[i] * nums[k] * nums[j] + dp[k][j];

其中,k 的值可以从 (i, j) 之间任选,所以应该枚举所有的 k 值,选择最大值来更新 dp[i][j]

之后,就从 (i,j) 开区间只有三个数字的时候开始计算,存储每个小区间可以得到的最多金币,然后慢慢扩展到更大的区间,利用小区间里已经算好的数字来算更大的区间。

因此,这道题的第一层遍历是按照区间长度(从3开始,因为我们设置了一个辅助数组,后面会详细解释),第二层遍历是按照左端点的索引,第三层索引是 k 的索引。

初始化

这里设置了一个辅助数字 temp ,用于处理边界问题,当只剩下一个气球的时候,此时的开区间左边界 i = 0, 右边界 j = n+1 ,这两个位置是没有气球的,根据题意,当它们是数字为 1 的气球,所以将它们的值设置为 1 。

因此,我们的区间长度就扩大了 2

所以,当 n = 1 时,区间长度从 3 开始考虑。

最终的返回结果

最后返回开区间(0, n+1) 内的最多金币。

代码

class Solution {
public:
    int maxCoins(vector<int>& nums) {
        int n = nums.size();
        vector<vector<int>> dp(n+2, vector<int>(n+2, 0));
        vector<int> temp(n+2);

        // 辅助数组
        temp[0] = temp[n+1] = 1;
        for(int i=0; i<n; ++i){
            temp[i+1] = nums[i];
        }
        // len表示开区间长度
        for(int len = 3; len <=n+2; len++){
            // i表示开区间的左端点(取不到 所以从0开始)
            for(int l=0; l<=n-len+2; l++){
                // 右端点为:r = l+len-1
                int r = l + len - 1;
                for(int k=l+1; k<r; ++k){
                    dp[l][r] = max(dp[l][r], dp[l][k] + temp[l]*temp[k]*temp[r] + dp[k][r]);
                }
            }
        }
        return dp[0][n+1];
    }
};

思考

阅读大佬解法的时候,发现了他使用了动态规划对例子进行分析,一步步得到答案,这个思路蛮值得我学习的:

在这里插入图片描述

解法二:分治法+记忆化搜索

其实理解完解法一之后,分治法的思想很好理解。

使用分治法时,我们应该考虑的核心问题是「如何用子问题的解来表示原问题的解」,我们把描述子问题的解与原问题的解之间的关系的表达式称为状态转移方程,这里和动态规划是一致的。毕竟,分治法就是分而治之,最后自底向上的合并过程就是动态规划的解决过程。

子问题的思考

按照一般的思路,首先思考能不能直接将[3, 1, 5, 8]直接分为类似于[3]、[1, 5, 8]这样两个子问题。这意味着,我们强行认为必须戳完 [3] 才能戳 [1, 5, 8],或者戳完[1, 5, 8]才能戳[3],显然这不科学。即这两个子问题之间产生了依赖

如何消除依赖呢?我们一开始的想法是先假设第一个被戳爆的气球为x,则x两边的气球则产生了依赖;那我们假设不戳爆x,则x两边的气球就没有了依赖关系!这个气球x,我们可以放在最后戳爆它

这样,对于[3, 1, 5, 8],假设最后戳爆5,则问题就被划分为如下图所示的两个子问题和一个O(1)的问题

在这里插入图片描述

因此,分析到这里,和动态规划就相同了,要想求得大数组的最优解,就必须求得左右两个小数组的最优解。不同的是,在分治法中,我们使用递归来实现。

一样地,也需要遍历开区间(i,j)内的每一个气球,作为最后戳爆的气球。

即:ans = max(ans, maxsubCoins(temp, begin, k, cache) + temp[begin]*temp[k]*temp[end] + maxsubCoins(temp, k, end, cache));

此外,增加 cache 数组保存已经计算过的区间的最优解,避免重复计算。

问题

由于参考的代码是 java,转变成我自己的代码会超时,一直没办法解决,因此正确代码请见参考资料

代码

// 超时
class Solution {
public:
    int maxsubCoins(vector<int>& temp, int begin, int end, vector<vector<int>> cache){
        // 说明剩下的两个气球相邻 无法戳破
        if(begin + 1 == end){
            return 0;
        }

        // 在缓存中查找,避免重复计算
        if(cache[begin][end] != 0){
            return cache[begin][end];
        }
        int ans = 0;
        // 找不到,开始计算
        for(int k=begin+1; k<end; ++k){
            ans = max(ans, maxsubCoins(temp, begin, k, cache) + temp[begin]*temp[k]*temp[end] + maxsubCoins(temp, k, end, cache));
        }
        cache[begin][end] = ans;
        return ans;
    }
    int maxCoins(vector<int>& nums) {
        int n = nums.size();
        vector<vector<int>> cache(n+2, vector<int>(n+2, 0));
        // 辅助数组的写法2
        nums.insert(nums.begin(),1);
        nums.push_back(1);
        return maxsubCoins(nums, 0, n+1, cache);
    }
};

参考资料

  1. Burst Balloons(leetcode戳气球,困难)从指数级时间复杂度到多项式级时间复杂度的超详细优化思路(回溯到分治到动态规划)
  2. 解题关键——“虚拟气球”,回溯,分治,动态规划。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/520607.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

UNIAPP框架中获取当前定位信息

概述 准备生成自己的Android证书。高德地图生成自己的key并配置mainfest.json。设置左上角图标并完成配置。页面中获取经纬度坐标。依据经纬度坐标获取位置信息。更新图标信息完成展示。 第一步&#xff1a;生成Android证书 参考资料 Android平台云端打包证书使用说明 https…

java类和对象之认识1

文章目录 一、Java类二、Java成员变量三、Java方法四、Java类的构造方法五、Java创建对象六、Java使用对象七、Java对象的引用和实体八、Java类与程序的基本结构九、Java参数传值总结 一、Java类 类是组成Java程序的基本要素&#xff0c;一个Java应用程序就是由若干个类所构成…

永磁同步电机(PMSM)无传感器控制基于龙伯格观测器Matlab/Simulink仿真分析

文章目录 前言一、龙伯格观测器1.1.龙伯格观测器的原理2.2.龙伯格观测器的误差2.3.PMSM龙伯格观测器的建立 二、Matlab/Simulink仿真分析2.1.仿真电路分析2.1.1.电机控制模式切换10ms任务2.1.2.速度环控制2ms任务2.1.3. 电流环控制50us任务2.1.4.电机主电路 2.2.仿真结果分析 总…

单调栈模板总结及应用

文章和代码已经归档至【Github仓库&#xff1a;https://github.com/timerring/algorithms-notes 】或者公众号【AIShareLab】回复 算法笔记 也可获取。 文章目录 单调栈模板栈算法模板例题&#xff1a;单调栈基本思路code 单调栈模板 栈&#xff1a;先进后出。 队列&#xff…

shell数组(包含排序算法)

目录 一&#xff1a;数组定义方法 1、方法一 2、方法二 ​3、方法三 ​4、方法四 5、判断数组是否完整 &#xff08;1&#xff09;方法一 &#xff08;2&#xff09;方法二&#xff1a;通过脚本 二&#xff1a;获取数组值 1、获取数组长度 2、获取数组数据列表 3、获…

ipad专用笔和其他笔有什么区别?第三方电容笔了解

要是ipad仅仅用来玩游戏&#xff0c;看电视的话&#xff0c;也太浪费ipad平板的作用了。ipad这个产品&#xff0c;用途还是很广的&#xff0c;既能用于职业绘画&#xff0c;又能用于学习笔记。许多人都觉得苹果的电容笔非常好&#xff0c;但与普通的电容笔相比&#xff0c;它的…

Python常用的开发工具合集

​ Python是一种功能强大且易于学习的编程语言&#xff0c;被广泛应用于数据科学、机器学习、Web开发等领域。随着Python在各个领域的应用越来越广泛&#xff0c;越来越多的Python开发工具也涌现出来。但是&#xff0c;对于新手来说&#xff0c;选择一款合适的Python开发工具可…

美本统计学基础笔记

美本统计学基础笔记 1.基础2.概率3.离散概率分布Discrete Probability Distributions4.The Normal Probability Distribution正态概率分布5.Sampling Distributions采样分布6.Large-Sample Estimation大样本估计7.Large-Sample Tests of Hypotheses假设的大样本检验 1.基础 左…

颜值打分代码实例讲解(paddle框架)

数据集介绍 训练数据集为华南理工大学实验室公布的数据集 数据中包含500张女生图片&#xff0c;分别由70人进行打分&#xff0c;最终取平均值即为该图片的打分情况。 我们在实践中将图片分值设定为1-5。 500张图片中&#xff0c;450张用于训练&#xff0c;50张用于验证。 任…

快速落地基于“AIGC+数字人”的数字化内容生产

谁不想有一个可爱的数字人形象呢&#xff1f;在日常的工作和娱乐中&#xff0c;越来越多的数字人虚拟形象与大家见面&#xff0c;他们可以是主播&#xff0c;也可以是语音助手&#xff0c;还可以是你自己的虚拟宠物。只有更快更精准的生成数字人&#xff0c;才能让数字人更加普…

【JS】1680- 重学 JavaScript API - Beacon API

❝ 前期回顾&#xff1a;1.Page Visibility API 2.Broadcast Channel API ❞ 1. 什么是 Beacon API 1.1 概念介绍 Beacon API 是 HTML5 提供的一种新的浏览器 API&#xff0c;可以用于在浏览器后台异步地发送数据&#xff0c;而不影响当前页面的加载和性能。通过 Beacon API&am…

FE_Vue学习笔记 常用指令的学习【v-model filters v-text v-html v-cloak v-once v-pre 自定义指令】

1 收集表单数据 v-model 收集表单数据&#xff1a; 若&#xff1a;<input type"text">&#xff0c;则v-model收集的是value的值&#xff0c;用户输入的就是value值。 若&#xff1a;<input type"radio">&#xff0c;则v-modle收集的是value的…

Eclipse配置tomcat服务器

1.首先下载tomcat&#xff0c;下载地址&#xff1a;http://maven.apache.org/&#xff0c;下载好后解压至本地磁盘根目录&#xff0c;我是解压至D盘根目录 2.打开Eclipse&#xff0c;进入Window->Preferences 3.找到Server->Runtime Environments 4.再右边点击Add添加一个…

【手撕代码】HDB3编解码

【手撕代码】HDB3编解码 1. 来源和需求 HDB3编解码任务来源于2023年3月4日“FPGA技术讨论群”的一次活动《101群第一次FPGA编码交流研讨会》&#xff0c;要求设计HDB3编解码&#xff0c;本篇文章作者【roy2022】&#xff0c;经作者授权后转发&#xff0c;以下所有文件版权归作者…

软考-高级系统架构师经验分享

【摘要】 2022年7月17从女朋友嘴里了解到有软考这个东西,7月20——7月23日,上班空闲时间百度详细了解了软考的内容、大纲、通过之后的收益,于是决定备考高级架构师考试并上网收集了所有能收集的资料(不论好坏,完成收集后再筛选);经过3个月的复习,2022年11月5日,第一次…

Extra Finance 主网测试版上线,完成任务领空投

DeFi 的广泛应用将上一轮牛市推向顶峰&#xff0c;也让区块链具有了更多的拓展性。经过熊市的洗礼&#xff0c;DeFi 应用开始升级和优化&#xff0c;并且衍生出更多更加具有实用性和创新性的新产品。DeFi 已经成为区块链的基础设施&#xff0c;为更多的应用和创新提供帮助。下一…

ENVI为不含地理参考信息的栅格影像手动添加地理、投影坐标系

本文介绍基于ENVI软件&#xff0c;对不含有任何地理参考信息的栅格遥感影像添加地理坐标系或投影坐标系等地理参考信息的方法。 我们先来看一下本文需要实现的需求。现有以下两景遥感影像&#xff0c;其位于不同的空间位置&#xff1b;但由于二者均不含任何地理参考信息&#…

SOFA Weekly|SOFAArk 社区会议回顾、Layotto 社区会议预告、社区本周贡献

SOFA WEEKLY | 每周精选 筛选每周精华问答&#xff0c;同步开源进展 欢迎留言互动&#xff5e; SOFAStack&#xff08;Scalable Open Financial Architecture Stack&#xff09;是蚂蚁集团自主研发的金融级云原生架构&#xff0c;包含了构建金融级云原生架构所需的各个组件&am…

Cisco 产品下载链接汇总 2023 持续更新中

Cisco 产品链接汇总 2023 持续更新中 IOS-XE, IOS-XR, NX-OS & FXOS based on linux kernel 请访问原文链接&#xff1a;https://sysin.org/blog/cisco/&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处。 作者主页&#xff1a;sysin.org 本站 Cisco 产品汇…

UE5利用Cesium for Unreal 部署和加载服务器上的倾斜摄影

主要步骤&#xff1a; 下载 Tomcat 下载 JDK 设置系统变量 运行UE程序 下载 Tomcat 网址&#xff1a;https://tomcat.apache.org/ 可以下载最新版&#xff0c;也可以下载历史版本&#xff0c;查看 2.下载JDK https://www.oracle.com/java/technologies/downloads/ 根据Tom…