Leetcode 312 打气球 Burst Balloons C++ 史上最详细题解系列

2023-12-25 06:58

本文主要是介绍Leetcode 312 打气球 Burst Balloons C++ 史上最详细题解系列,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

题目:


Given n balloons, indexed from 0 to n-1. Each balloon is painted witha number on it represented by array nums. You are asked to burst allthe balloons. If the you burst balloon i you will get nums[left] * nums[i] * nums[right] coins. Here left and right are adjacent indices of i. After the burst, the left and right then becomes adjacent.

Find the maximum coins you can collect by bursting the balloons wisely.

Note:

  1. You may imagine nums[-1] = nums[n] = 1. They are not real therefore you can not burst them.
  2. 0 ≤ n ≤ 500, 0 ≤ nums[i] ≤ 100、

Example:

  1. Given [3, 1, 5, 8]
  2. Return 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

有 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 =  3*1*5      +  3*5*8    +   1*3*8     + 1*8*1   = 167

这题实在是。。。太巧妙了,做的时候有感而发。

首先要知道的是要采用dp的方法做。

难点1
dp各项表示什么?

这关乎到做题选手的建模能力,我们代码中选择的是dp[i][j]等于从第i个数到第j个数的这个区间内的乘积最大值(包括i,j)

难点2
如何找递归式?

这里就更巧妙了,总的思路是先确定长度较小的区间,然后在这个区间里选一个数k成为最后一个被打爆的气球,dp[left][i-1]就是左边部分被打爆的最大值,dp[i+1][right]就是右边部分被打爆的最大值,所以我们只需要算最后一次打爆气球的分数再加上2旁区间打爆所有气球的最大值即可。读上面这句话三遍或以上直至读懂,读代码:

// Non-recursion
class Solution {
public:int maxCoins(vector<int>& nums) {int n = nums.size();//记录数组大小为nnums.insert(nums.begin(), 1);//在数组前加1nums.push_back(1);//后加1vector<vector<int> > dp(nums.size(), vector<int>(nums.size() , 0));//构造dp表,注意这时候nums.size()是加过2了的for (int len = 1; len <= n; ++len) {//遍历长度,这个长度len指的是区间[left,right]的长度for (int left = 1; left <= n - len + 1; ++left) {//遍历这个区间的起始点leftint right = left + len - 1;//通过上面的长度遍历求区间的结束点rightfor (int k = left; k <= right; ++k) {//遍历这个区间中的每个点dp[left][right] = max(dp[left][right], nums[left - 1] * nums[k] * nums[right + 1] + dp[left][k - 1] + dp[k + 1][right]);//dp[left][right]表示从left->right中所有点的连乘的最大值,包括left,right。//这个递推式的解释是,我选择k作为最后一个被消除的元素,那么这个区间的连乘的最大值为//nums[left-1]*nums[k]*nums[right+1](这时候left,right都不在了,因为k才是这个区间的最后一个元素,所以这个区间2边相邻的元素是nums[left-1],nums[right+1].这个式子表示最后一次计算的结果,//dp[left][k-1]指的是从left->k-1乘完后的最大值(包括left,k-1),dp[k+1][right]同理}}}return dp[1][n];//返回整个最大区间的连乘最大值(第1个到第n个)}
};

补充:

1.dp[left][k-1] , dp[k+1][right]是你想求就求啊,你以为这是递归函数?

答:这是这道题最巧妙的地方了,仔细看我们的for循环的顺序,第一次我们取长度为1的区间(也就是每个区间只有一个数),第二次for遍历时候取的长度为2的区间,这时候长度为1的区间的结果已经求出来了!刚好可以被长度为2的区间用到!伟大的dp!

2.行行行,那有些时候dp[k+1][right]里的k+1 > right了怎么说?

答:确实会出现这种情况,比如遍历长度为1的区间时。但是这并不影响做题,因为那些都会是0,经过初始化后还没动。

 
来源:CSDN 
原文:https://blog.csdn.net/weixin_41958153/article/details/81903551 

这篇关于Leetcode 312 打气球 Burst Balloons C++ 史上最详细题解系列的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/534604

相关文章

C#如何调用C++库

《C#如何调用C++库》:本文主要介绍C#如何调用C++库方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录方法一:使用P/Invoke1. 导出C++函数2. 定义P/Invoke签名3. 调用C++函数方法二:使用C++/CLI作为桥接1. 创建C++/CL

IntelliJ IDEA 中配置 Spring MVC 环境的详细步骤及问题解决

《IntelliJIDEA中配置SpringMVC环境的详细步骤及问题解决》:本文主要介绍IntelliJIDEA中配置SpringMVC环境的详细步骤及问题解决,本文分步骤结合实例给大... 目录步骤 1:创建 Maven Web 项目步骤 2:添加 Spring MVC 依赖1、保存后执行2、将新的依赖

如何为Yarn配置国内源的详细教程

《如何为Yarn配置国内源的详细教程》在使用Yarn进行项目开发时,由于网络原因,直接使用官方源可能会导致下载速度慢或连接失败,配置国内源可以显著提高包的下载速度和稳定性,本文将详细介绍如何为Yarn... 目录一、查询当前使用的镜像源二、设置国内源1. 设置为淘宝镜像源2. 设置为其他国内源三、还原为官方

最详细安装 PostgreSQL方法及常见问题解决

《最详细安装PostgreSQL方法及常见问题解决》:本文主要介绍最详细安装PostgreSQL方法及常见问题解决,介绍了在Windows系统上安装PostgreSQL及Linux系统上安装Po... 目录一、在 Windows 系统上安装 PostgreSQL1. 下载 PostgreSQL 安装包2.

C++如何通过Qt反射机制实现数据类序列化

《C++如何通过Qt反射机制实现数据类序列化》在C++工程中经常需要使用数据类,并对数据类进行存储、打印、调试等操作,所以本文就来聊聊C++如何通过Qt反射机制实现数据类序列化吧... 目录设计预期设计思路代码实现使用方法在 C++ 工程中经常需要使用数据类,并对数据类进行存储、打印、调试等操作。由于数据类

MySql match against工具详细用法

《MySqlmatchagainst工具详细用法》在MySQL中,MATCH……AGAINST是全文索引(Full-Textindex)的查询语法,它允许你对文本进行高效的全文搜素,支持自然语言搜... 目录一、全文索引的基本概念二、创建全文索引三、自然语言搜索四、布尔搜索五、相关性排序六、全文索引的限制七

Linux下如何使用C++获取硬件信息

《Linux下如何使用C++获取硬件信息》这篇文章主要为大家详细介绍了如何使用C++实现获取CPU,主板,磁盘,BIOS信息等硬件信息,文中的示例代码讲解详细,感兴趣的小伙伴可以了解下... 目录方法获取CPU信息:读取"/proc/cpuinfo"文件获取磁盘信息:读取"/proc/diskstats"文

python中各种常见文件的读写操作与类型转换详细指南

《python中各种常见文件的读写操作与类型转换详细指南》这篇文章主要为大家详细介绍了python中各种常见文件(txt,xls,csv,sql,二进制文件)的读写操作与类型转换,感兴趣的小伙伴可以跟... 目录1.文件txt读写标准用法1.1写入文件1.2读取文件2. 二进制文件读取3. 大文件读取3.1

Linux内核参数配置与验证详细指南

《Linux内核参数配置与验证详细指南》在Linux系统运维和性能优化中,内核参数(sysctl)的配置至关重要,本文主要来聊聊如何配置与验证这些Linux内核参数,希望对大家有一定的帮助... 目录1. 引言2. 内核参数的作用3. 如何设置内核参数3.1 临时设置(重启失效)3.2 永久设置(重启仍生效

C++使用printf语句实现进制转换的示例代码

《C++使用printf语句实现进制转换的示例代码》在C语言中,printf函数可以直接实现部分进制转换功能,通过格式说明符(formatspecifier)快速输出不同进制的数值,下面给大家分享C+... 目录一、printf 原生支持的进制转换1. 十进制、八进制、十六进制转换2. 显示进制前缀3. 指