leetcode刷题(77)——312. 戳气球

2023-11-19

一、题目

有 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

二、思路——动态规划

对于求最值问题,我们想到回溯法和动态规划,这里我们用动态规划来解决。

定义状态:

题目中说你可以假设 n u m s [ − 1 ] = n u m s [ n ] = 1 nums[-1] = nums[n] = 1 nums[1]=nums[n]=1,我们先把这两个边界加到数组中,形成一个新的长度为 n + 2 n + 2 n+2 的数组 points,其中 p o i n t s [ 0 ] = p o i n t s [ n + 1 ] = 1 points[0] = points[n + 1] = 1 points[0]=points[n+1]=1,那么我们要戳破的就是从 1 到 n n n 的所有气球。

我们要求的是戳破所有的气球能获得的硬币的最大数量,换句话说就是,戳破气球 0 和气球 n + 1 n + 1 n+1 之间的气球能获得的硬币的最大数量。据此我们可以定义状态, d p [ i ] [ j ] dp[i][j] dp[i][j] 表示戳破气球 i 和气球 j 之间(开区间,不包括 i 和 j)的所有气球能获得的硬币的最大数量

推导状态转移方程:

状态转移的过程其实就是我们在每一步怎么做选择的过程。现在要求 d p [ i ] [ j ] dp[i][j] dp[i][j],假设我们每一步都选择戳破能够获得硬币数量最大的那个气球,最后只剩下一个气球的时候,没得选只能戳破该气球。所以我们要考虑的是气球 i 和 气球 j 之间最后被戳破的气球是哪个,不妨设为 k。那么戳破气球 k 能得到的金币数为 p o i n t s [ i ] ∗ p o i n t s [ k ] ∗ p o i n t s [ j ] points[i] * points[k] * points[j] points[i]points[k]points[j],那 d p [ i ] [ j ] dp[i][j] dp[i][j] 的值就是: 戳 破 ( i , k ) 之 间 的 气 球 获 得 的 最 大 硬 币 数 + 戳 破 ( k , j ) 之 间 的 气 球 获 得 的 最 大 硬 币 数 + 戳 破 气 球 k 获 得 的 硬 币 数 戳破(i, k)之间的气球获得的最大硬币数 + 戳破 (k,j)之间的气球获得的最大硬币数 + 戳破气球 k 获得的硬币数 (i,k)+(k,j)+k d p [ i ] [ j ] = d p [ i ] [ k ] + d p [ k ] [ j ] + p o i n t s [ i ] ∗ p o i n t s [ k ] ∗ p o i n t s [ j ] dp[i][j] = dp[i][k] + dp[k][j] + points[i] * points[k] * points[j] dp[i][j]=dp[i][k]+dp[k][j]+points[i]points[k]points[j] 其中 i < k < j i <k < j i<k<j

意思就是,我们穷举 i < k < j i <k < j i<k<j,求出把每个 k 都看作最后一个戳破的气球时能获得的最大硬币数,选择硬币最多的方案。

遍历方向:

d p [ i ] [ j ] dp[i][j] dp[i][j] 所依赖的状态是 d p [ i ] [ k ] dp[i][k] dp[i][k] d p [ k ] [ j ] dp[k][j] dp[k][j],那么我们必须保证:在计算 d p [ i ] [ j ] dp[i][j] dp[i][j]时, d p [ i ] [ k ] dp[i][k] dp[i][k] d p [ k ] [ j ] dp[k][j] dp[k][j] 已经被计算出来了(其中 i < k < j)。我们的目标是求出戳破所有的气球能获得的最大硬币数,即最后返回 d p [ 0 ] [ n + 1 ] dp[0][n + 1] dp[0][n+1] 的值,由此看出 i 是从大到小的,j 是从小到大的。

边界条件:

数组初始化:当 j ≤ i + 1 j \leq i +1 ji+1 时, d p [ i ] [ j ] = 0 dp[i][j] = 0 dp[i][j]=0,因为此时 ( i , j ) (i,j) (i,j) 之间没有气球了。

三、代码

class Solution {
    public int maxCoins(int[] nums) {
        int n = nums.length;
        // 把两个虚拟气球添加到数组中
        int[] points = new int[n + 2];
        points[0] = points[n + 1] = 1;
        for(int i = 1; i <= n; i++){
            points[i] = nums[i - 1];
        }
        int[][] dp = new int[n + 2][n + 2];// 数组默认为0,不用再写初始化条件了
        for(int i = n; i >= 0; i--){// i从大到小
            for(int j = i + 1; j < n + 2; j++){// j从小到大
                // 最后戳破的是哪个?选择硬币数最大的方案
                for(int k = i + 1; k < j; k++){
                    dp[i][j] = Math.max(dp[i][j], dp[i][k] + dp[k][j] + points[i] * points[k] * points[j]);
                }
            }
        }
        return dp[0][n + 1];
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

leetcode刷题(77)——312. 戳气球 的相关文章

随机推荐

  • 如何访问虚拟机中的Web服务

    需求 1 在虚拟机Vmware中安装了CentOS6 5 虚拟机使用NAT的方式 2 在CentOS中安装了APACHE 并且使用 http 192 168 237 128可以正常访问 3 想在其他windows机器上访问该虚拟机的web服
  • linux系统的系统性学习 (持续更新)

    分类 系统启动过程 第一步 内核的引导 第二步 运行 init 第三步 系统初始化 第四步 建立终端 第五步 用户登录系统 关机 查看系统基本信息 CPU相关 内存相关 查看网络信息 用户 服务 进程相关 磁盘管理 df 命令 du 命令
  • Thrift、Dubbo、Spring Cloud 和 gRPC

    何为RPC RPC Remote Procedure Call 远程过程调用 是一种进程间通信方式 是一种技术的思想 而不是规范 它允许程序调用另一个地址空间 通常是共享网络的另一台机器上 的过程或函数 而不用程序员显式编码这个远程调用的细
  • 计算机常用函数及写法,计算机常用的函数公式有哪些?

    01 计算机常用的函数公式包括RANK函数 COUNTIF函数 IF函数 ABS函数 AND函数 AVERAGE函数 COLUMN 函数等 RANK函数是Excel计算序数的主要工具 它的语法为 RANK number ref order
  • 现代OpenGL教程 01 - 入门指南

    文章转载自 http huangwei pro 2015 05 modern opengl1 以下是我学习opengl得到的启示最多的一篇文章 我强烈地建议大家去读一下这位大神的相关系列的文章 还有https github com tomd
  • Allegro约束管理器的设置

    1 打开约束管理器 2 设置管理器 黄色表示未打开 右击 选择analysis mode打开 3 添加物理规则 修改的数据 4 建立组 同时选中几个网络 右击选择Create New Group新建一个组 修改组的规则里面的网络也都跟着修改
  • Orangepi Zero2 全志H616 的初识

    Q 为什么要学习香橙派 A 在之前对于Linux系统的学习 其内容主要是对于系统API的掌握 而很难进行外设的交互 Linux系统很强大 如果能够结合外设 可以做出STM32 C52等单片机无法实现的复杂项目 而我们可以通过将Linux系统
  • Python 中导入csv数据的三种方法

    这篇文章主要介绍了Python 中导入csv数据的三种方法 内容比较简单 非常不错 具有一定的参考借鉴价值 需要的朋友可以参考下微点阅读小编收集的文章介绍 Python 中导入csv数据的三种方法 具体内容如下所示 1 通过标准的Pytho
  • lnmp集群的搭建及优化

    文章目录 lnmp 名词解释 搭建 mysql nginx php 一键安装 优化及应用 Discuz论坛搭建 php增加memcache模块 nginx添加memcache模块 tomcat lnmp 名词解释 LNMP是指一组通常一起使
  • 服务器上配置jupyter并使用浏览器远程连接

    一 服务器上配置jupyter 1 安装jupyter 执行两条安装命令 conda install ipykernel conda install jupyter 2 添加配置文件 jupyter notebook generate co
  • vi vim快捷键

    快捷键 行为 x 删除光标所在后面的字符 X 删除光标所在前面的字符 d e 删除光标所在位置到本单词末尾 d E 删除光标所在位置到本单词末尾包括标点符号 d b 删除光标所在位置到前面单词 d B 删除光标所在位置到前面单词包括标点符号
  • 机器学习——Boosting、提升树、随机森林(Random Forest)学习笔记

    大数据工作室学习打卡 第 N 次 一 Boosting 提升 1 什么是集成学习 首先 我们得先了解什么是集成学习 集成学习是一种通过组合弱学习器来产生强学习器的通用且有效的方法 简单来说 就是通过训练多个分类器 然后将其组合起来 从而达到
  • 定时开机电路设计

    在一些情况下 比如电池供电 需要定时采集数据并传输 并且对功耗要求比较高时 就需要电路实现采集完成后关机 且能够定时自动启动的功能 一种方法是 采集完成后 通过单片机关闭外围电路的电源 且单片机本身处于低功耗模式 只保留RTC工作 设置定时
  • 为女朋友写一个小程序(四)— —前端小程序的设计与实现

    为女朋友写一个小程序 一 目的与需求 为女朋友写一个小程序 二 数据库设计 为女朋友写一个小程序 三 基于springboot的服务器端接口设计与实现 为女朋友写一个小程序 四 前端小程序的设计与实现 本文 为女朋友写一个小程序 五 如何用
  • Tensorflow常见报错

    1 SyntaxError Non ASCII character xe5 in file 弹出的错误提示 这个错误是初学者常犯的错误 在写代码时一定要注意 问题原因 Python默认是以ASCII作为编码方式的 如果在自己的Python源
  • train loss 和 test loss的关系与作用(总结)

    train loss 不断下降 test loss不断下降 说明网络仍在学习 最好的 train loss 不断下降 test loss趋于不变 说明网络过拟合 max pool或者正则化 train loss 趋于不变 test loss
  • 【云原生之kubernetes】kubernetes集群下的健康检查使用方法

    云原生之kubernetes kubernetes集群下的健康检查使用方法 一 k8s健康检查介绍 1 k8s健康检查简介 2 k8s健康检查作用 二 检查本地kubernetes集群状态 1 检查工作节点状态 2 检查系统pod状态 三
  • 以太坊如何发布NFT到opensea

    前提说明 此篇文章主要讲解 如何发布类似于网址 https killaznft com 或者 https thesevensofficial com 这种基于项目方的NFT 进行网页售卖以及上架到OpenSea上进行展示和售卖的过程 对技术
  • 记录帖——项目中出现的某些问题

    1 问题 自制的PCB板串口出现某些未知的错误 硬件平台 芯片是STM32F103RBT6 引出了3个串口 1个I2C SWD烧写 USART1接ESP8266 用于输出字符串 USART2接MPU6050 串口输出 USART3接GPS
  • leetcode刷题(77)——312. 戳气球

    一 题目 有 n 个气球 编号为0 到 n 1 每个气球上都标有一个数字 这些数字存在数组 nums 中 现在要求你戳破所有的气球 每当你戳破一个气球 i 时 你可以获得 nums left nums i nums right 个硬币 这里