Top 100 Linked Question 修炼------第312题

2024-01-02 17:18

本文主要是介绍Top 100 Linked Question 修炼------第312题,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

312. Burst Balloons

题目链接

题目解释

给出n个气球,他们的角标从0到n-1。每个气球上面都画有数字,代表数组中的元素。现在要求你将所有的气球都爆破,如果你选择爆破第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

Example:

Input: 
[3,1,5,8]Output: 
167 
Explanation: 
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

题目分析

首先,按照题目的提示,我们为了避免越界情况的发生,应该先在首尾分别加上元素1,并且保证这两个气球是不能被戳破的。然后我们开始分析,怎么才能获取最大的钱币数。既然出现了最多这个词汇,那么就可以考虑往动态规划(DP)方向去思考,最主要的是建立状态转移方程,下面开始分析过程:

这道题的最难点就是找状态转移方程,还是从定义式来看,假如区间只有一个数,比如 dp[i][i],那么计算起来就很简单,直接乘以周围两个数字即可更新。如果区间里有两个数字,那么就要算两次了,先打破第一个再打破了第二个,或者先打破第二个再打破第一个,比较两种情况,其中较大值就是该区间的dp值。假如区间有三个数呢,比如 dp[1][3],怎么更新呢?如果先打破第一个,剩下两个怎么办呢,难道还要分别再遍历算一下吗?这样跟暴力搜索的方法有啥区别呢,还要 dp 数组有啥意思。所谓的状态转移,就是假设已知了其他状态,来推导现在的状态,现在是想知道 dp[1][3] 的值,那么如果我们先打破了气球1,剩下了气球2和3,若我们之前已经计算了 dp[2][3] 的话,就可以使用其来更新 dp[1][3] 了,就是打破气球1的得分加上 dp[2][3]。那假如我们先打破气球2呢,只要我们之前计算了 dp[1][1] 和 dp[3][3],那么三者加起来就可以更新 dp[1][3]。同理,先打破气球3,就用其得分加上 dp[1][2] 来更新 dp[1][3]。

那么对于有很多数的区间 [i, j],我们如何来更新呢?现在是想知道 dp[i][j] 的值,这个区间可能比较大,但是如果我们知道了所有的小区间的 dp 值,然后聚沙成塔,逐步的就能推出大区间的 dp 值了。还是要遍历这个区间内的每个气球,就用k来遍历吧,k在区间 [i, j] 中,假如第k个气球最后被打爆,那么此时区间 [i, j] 被分成了三部分,[i, k-1],[k],和 [k+1, j],只要我们之前更新过了 [i, k-1] 和 [k+1, j] 这两个子区间的 dp 值,可以直接用 dp[i][k-1] 和 dp[k+1][j],那么最后被打爆的第k个气球的得分该怎么算呢,你可能会下意识的说,就乘以周围两个气球被 nums[k-1] * nums[k] * nums[k+1],但其实这样是错误的,为啥呢?dp[i][k-1] 的意义是什么呢,是打爆区间 [i, k-1] 内所有的气球后的最大得分,此时第 k-1 个气球已经不能用了,同理,第 k+1 个气球也不能用了,相当于区间 [i, j] 中除了第k个气球,其他的已经爆了,那么周围的气球只能是第 i-1 个,和第 j+1 个了,所以得分应为 nums[i-1] * nums[k] * nums[j+1],分析到这里,我们的状态转移方程应该已经跃然纸上了吧,如下所示:

dp[i][j] = max(dp[i][j], nums[i - 1] * nums[k] * nums[j + 1] + dp[i][k - 1] + dp[k + 1][j])                 ( i ≤ k ≤ j )

有了状态转移方程了,我们可以写代码,下面就遇到本题的第二大难点了,区间的遍历顺序。一般来说,我们遍历所有子区间的顺序都是i从0到n,然后j从i到n,然后得到的 [i, j] 就是子区间。但是这道题用这种遍历顺序就不对,在前面的分析中已经说了,我们需要先更新完所有的小区间,然后才能去更新大区间,而用这种一般的遍历子区间的顺序,会在更新完所有小区间之前就更新了大区间,从而不一定能算出正确的dp值,比如拿题目中的那个例子 [3, 1, 5, 8] 来说,一般的遍历顺序是:

[3] -> [3, 1] -> [3, 1, 5] -> [3, 1, 5, 8] -> [1] -> [1, 5] -> [1, 5, 8] -> [5] -> [5, 8] -> [8] 

显然不是我们需要的遍历顺序,正确的顺序应该是先遍历完所有长度为1的区间,再是长度为2的区间,再依次累加长度,直到最后才遍历整个区间:

[3] -> [1] -> [5] -> [8] -> [3, 1] -> [1, 5] -> [5, 8] -> [3, 1, 5] -> [1, 5, 8] -> [3, 1, 5, 8]

我们其实只是更新了 dp 数组的右上三角区域,我们最终要返回的值存在 dp[1][n] 中,其中n是两端添加1之前数组 nums 的个数。参见代码如下:

class Solution:def maxCoins(self, nums):""":param nums::return:"""# 首先将nums首尾均加上1,避免最后乘法判断以及出现越界的情况nums = [1] + [n for n in nums if n != 0] + [1]# 初始化dp,dp[left][right]代表爆炸掉(left, right)范围(不包含两侧)的所有气球的最大coin数。dp = [[0 for i in range(len(nums))] for j in range(len(nums))]for balloons_to_burst in range(1, len(nums) - 1):# number of balloons in (l,r) regionfor l in range(0, len(nums) - balloons_to_burst - 1):# for m and r to be assigned legallyr = l + balloons_to_burst + 1for m in range(l + 1, r):dp[l][r] = max(dp[l][r],dp[l][m] + dp[m][r] + nums[l] * nums[m] * nums[r])return dp[0][-1]

总结

2019/6/13 每个动态规划都要推导一遍....

Reference

https://www.cnblogs.com/grandyang/p/5006441.html

这篇关于Top 100 Linked Question 修炼------第312题的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

安卓玩机工具------小米工具箱扩展工具 小米机型功能拓展

小米工具箱扩展版                     小米工具箱扩展版 iO_Box_Mi_Ext是由@晨钟酱开发的一款适用于小米(MIUI)、多亲(2、2Pro)、多看(多看电纸书)的多功能工具箱。该工具所有功能均可以免root实现,使用前,请打开开发者选项中的“USB调试”  功能特点 【小米工具箱】 1:冻结MIUI全家桶,隐藏状态栏图标,修改下拉通知栏图块数量;冻结

【LeetCode热题100】前缀和

这篇博客共记录了8道前缀和算法相关的题目,分别是:【模版】前缀和、【模版】二维前缀和、寻找数组的中心下标、除自身以外数组的乘积、和为K的子数组、和可被K整除的子数组、连续数组、矩阵区域和。 #include <iostream>#include <vector>using namespace std;int main() {//1. 读取数据int n = 0, q = 0;ci

牛客小白月赛100部分题解

比赛地址:牛客小白月赛100_ACM/NOI/CSP/CCPC/ICPC算法编程高难度练习赛_牛客竞赛OJ A.ACM中的A题 #include<bits/stdc++.h>using namespace std;#define ll long long#define ull = unsigned long longvoid solve() {ll a,b,c;cin>>a>>b>

牛客小白月赛100(A,B,C,D,E,F三元环计数)

比赛链接 官方讲解 这场比较简单,ABC都很签到,D是个不太裸需要预处理的 B F S BFS BFS 搜索,E是调和级数暴力枚举,F是三元环计数。三元环考的比较少,没见过可能会偏难。 A ACM中的A题 思路: 就是枚举每个边变成原来的两倍,然后看看两短边之和是否大于第三边即可。 不能只给最短边乘 2 2 2,比如 1 4 8 这组数据,也不能只给第二短边乘 2 2 2,比

诺瓦星云校招嵌入式面试题及参考答案(100+面试题、10万字长文)

SPI 通信有哪些内核接口? 在嵌入式系统中,SPI(Serial Peripheral Interface,串行外设接口)通信通常涉及以下内核接口: 时钟控制接口:用于控制 SPI 时钟的频率和相位。通过设置时钟寄存器,可以调整 SPI 通信的速度以适应不同的外设需求。数据发送和接收接口:负责将数据从主机发送到从机以及从从机接收数据到主机。这些接口通常包括数据寄存器,用于存储待发

多个线程如何轮流输出1到100

多个线程如何轮流输出1到100的值 这个面试问题主要考察如何让线程同步,首先线程同步必会用到的就是互斥锁,互斥锁保证多个线程对数据的同时操作不会出错。但是线程同步还会用到条件变量condition_variable,condition_variable(条件变量)是 C++11 中提供的一种多线程同步机制,它允许一个或多个线程等待另一个线程发出通知,以便能够有效地进行线程同步。 conditi

【最新华为OD机试E卷-支持在线评测】机器人活动区域(100分)多语言题解-(Python/C/JavaScript/Java/Cpp)

🍭 大家好这里是春秋招笔试突围 ,一枚热爱算法的程序员 ✨ 本系列打算持续跟新华为OD-E/D卷的三语言AC题解 💻 ACM金牌🏅️团队| 多次AK大厂笔试 | 编程一对一辅导 👏 感谢大家的订阅➕ 和 喜欢💗 🍿 最新华为OD机试D卷目录,全、新、准,题目覆盖率达 95% 以上,支持题目在线评测,专栏文章质量平均 94 分 最新华为OD机试目录: https://blog.

PostgreSQL 17即将发布,新功能Top 3

按照计划,PostgreSQL 17 即将在 2024 年 9 月 26 日发布,目前已经发布了第一个 RC 版本,新版本的功能增强可以参考 Release Notes。 本文给大家分享其中 3 个重大的新增功能。 MERGE 语句增强 MERGE 语句是 PostgreSQL 15 增加的一个新功能,它可以在单个语句中实现 INSERT、UPDATE 以及 DELETE 操作,非常适合数据

华为OD机试 - 最大利润(Java 2024 E卷 100分)

华为OD机试 2024E卷题库疯狂收录中,刷题点这里 专栏导读 本专栏收录于《华为OD机试(JAVA)真题(E卷+D卷+A卷+B卷+C卷)》。 刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新,全天CSDN在线答疑。 一、题目描述

AIGC与数据分析融合,引领商业智能新变革(TOP企业实践)

AIGC与数据分析融合,引领商业智能新变革(TOP企业实践) 前言AIGC与数据分析融合 前言 在当今数字化时代,数据已成为企业发展的核心资产,而如何从海量数据中挖掘出有价值的信息,成为了企业面临的重要挑战。随着人工智能技术的飞速发展,AIGC(人工智能生成内容)与数据分析的融合为企业提供了新的解决方案。 阿里巴巴作为全球领先的科技公司,一直致力于探索和应用前沿技术,以提升企业