动态规划算法题刷题笔记

首先看动态规划的三要素:重叠子问题、最优子结构和状态转移方程。

重叠子问题:存在大量的重复计算

最优子结构:

状态转移方程:当前状态转移成以前的状态

动态规划的解题步骤主要有:

  • 确定 dp 数组以及下标的含义
  • 状态转移方程、递推公式
  • dp数组初始化、遍历顺序
  • 写代码验证

直接看实际的算法题

1.LeetCode70. 爬楼梯

假设你正在爬楼梯。需要 n 阶你才能到达楼顶。

每次你可以爬 12 个台阶。你有多少种不同的方法可以爬到楼顶呢?

示例 1:

输入:n = 2
输出:2
解释:有两种方法可以爬到楼顶。
1. 1 阶 + 1 阶
2. 2 阶

实际上就是斐波那契算法,我们按最后一次爬楼梯的情形:只有爬1个或者2个台阶,如下图:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

所以状态转移方程就是 f(n) = f(n-1) + f(n-2)

public int climbStairs(int n) {if(n == 1) {return 1;}int[] dp = new int[n + 1];dp[0] = 1;dp[1] = 1;dp[2] = 2;for(int i = 3; i <= n; i++) {dp[i] = dp[i - 1] + dp[i - 2];}return dp[n];
}

变体:如果可以爬1、2、3、4…m 级台阶,如何求最后的次数?根据上面的图可以得到状态方程:

f(n) = f(n-1) + f(n-2) +...+f(n - m)所以解题代码为:

public int climbStairs2(int n) {int[] dp = new int[n+1];dp[0] = 1;for(int i = 1; i <= n; i++) {for(int j = 1; i <= m; j++) {if(i - j >= 0) {dp[i] = dp[i - j];}}}return dp[n];
}
2.LeetCode746. 使用最小花费爬楼梯

给你一个整数数组 cost ,其中 cost[i] 是从楼梯第 i 个台阶向上爬需要支付的费用。一旦你支付此费用,即可选择向上爬一个或者两个台阶。

只能选择从下标为 0 或下标为 1 的台阶开始爬楼梯,

请你计算并返回达到楼梯顶部的最低花费。

示例 1:

输入:cost = [10,15,8]
输出:15
解释:你将从下标为 1 的台阶开始。- 支付 15 ,向上爬两个台阶,到达楼梯顶部。总花费为 15 。

这题的思路和上一题爬楼梯很像,我们还是自顶向下来考虑,

如果最后一次选择记为f(n) 那么需要考虑f(n-1)f(n-2)谁更小,然后再加上当前的花费值。那么状态转移方程为:f(n) = min(f(n-1), f(n-2)) + cost[n]。因此代码就容易了:

public int minCostClimbingStairs(int[] cost) {int[] dp = new int[cost.length];dp[0] = cost[0];dp[1] = cost[1];for(int i = 2; i < cost.length; i++) {dp[i] = Math.min(dp[i - 1], dp[i - 2]) + cost[i];}//因为可以一次性爬两层,所以最后再比较倒数一次和倒数第二次的爬楼梯花费return Math.min(dp[cost.length - 1], dp[cost.length - 2]);
}
3.LeetCode62. 不同路径

一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为 “Start” )。

机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish” )。

问总共有多少条不同的路径?

示例 1:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

输入:m = 3, n = 7
输出:28

看题目可以知道,和前两题不一样,需要我们从两个维度去考虑。因此可以选择二维dp数组来解决问题,按照动态规划解题步骤:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  1. 确定dp数组的含义
    • dp[m][n] 表示从 [0][0][m][n] 的路径条数,数组内的下标表示所处的位置
  2. 确定状态转移方程
    • 我们知道当前位置状态来源于左侧和上侧位置状态因此可以写成:
    • dp[m][n] = dp[m-1][n] +dp[m][n-1]
  3. 确定dp数组初始状态和遍历顺序
    • 初始状态要注意,和一维dp数组考虑一个初始值不同。我们要考虑二维多个初始值:
      • dp[0][i]dp[j][0] 这两列上,路径条数都应该为1
    • 遍历顺序,按照从小到大的原则进行

综合上面的思路,可以写出代码

public int uniquePaths(int m, int n) {int[][] dp = new int[m][n];//初始化dp数组for(int i = 0; i < m; i++) dp[i][0] = 1;for(int j = 0; j < n; j++) dp[0][j] = 1;//遍历顺序for(int i = 1; i < m; i++) {for(int j = 1; j < n; j++) {//状态转移方程dp[i][j] = dp[i][j - 1] + dp[i - 1][j];}}return dp[m - 1][n - 1];
}
4.LeetCode63. 不同路径 II

一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为 “Start” )。

机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish”)。

现在考虑网格中有障碍物。那么从左上角到右下角将会有多少条不同的路径?

网格中的障碍物和空位置分别用 1 和 0 来表示。

示例 1:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

输入:obstacleGrid = [[0,0,0],[0,1,0],[0,0,0]]
输出:2
解释:3x3 网格的正中间有一个障碍物。
从左上角到右下角一共有 2 条不同的路径:1. 向右 -> 向右 -> 向下 -> 向下
2. 向下 -> 向下 -> 向右 -> 向右

这题和上一题的区别就是有了障碍,那么我们该如何考虑这个障碍呢?主要分成两个方面:

  • 初始化时遇到障碍:

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • 顺序遍历时遇到障碍:

    也就是题目给出的情况,这种情况将障碍处设置为0 即可

其余的和上一题类似,所以直接给出代码:

public int uniquePathsWithObstacles(int[][] obstacleGrid) {// 数组的行数int m = obstacleGrid.length;// 数组的列数int n = obstacleGrid[0].length;int[][] dp = new int[m][n];//障碍及后面方格统一初始化for(int i = 0; i < m; i++) {if(obstacleGrid[i][0] == 1) {break;}dp[i][0] = 1;}for(int j = 0; j < n; j++) {if(obstacleGrid[0][j] == 1) {break;}dp[0][j] = 1;}for(int i = 1; i < m; i++) {for(int j = 1; j < n; j++) {//遍历过程遇见障碍,直接跳过if(obstacleGrid[i][j] == 1) {dp[i][j] = 0;continue;}dp[i][j] = dp[i - 1][j] + dp[i][j - 1];}}return dp[m - 1][n - 1];
}
5.leetCode343. 整数拆分

给定一个正整数 n ,将其拆分为 k正整数 的和( k >= 2 ),并使这些整数的乘积最大化。

返回 你可以获得的最大乘积

示例 1:

输入: n = 2
输出: 1
解释: 2 = 1 + 1, 1 × 1 = 1。

我们按照动态规划解题步骤一步步来:

  • 1.确定dp数组的含义以及下标:

    • dp数组表示的是最大乘积,下标表示整数n
  • 2.确定状态转移方程:

    • 考虑到一个整数至少要分成2个及以上的整数,所以:

      • 分成2个可以表达成 i * j
      • 分成2个以上可以表达成 j * dp[i - j]
    • 所以转移方程应该为: dp[i] = max(j * dp[i - j], j * i)

      • 但是这里我们会发现得不到符合题意的值:

        外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

        因为每次取的都是最后一个,比如 dp[10] = max(9 * dp[1], 9 * 1) ,所以每次需要与前面的 dp[i] 比较,得到最后的最大值。

      • 因此转移方程应为:dp[i] = max(dp[i],max(j * dp[i - j], j * (i - j)))

  • 3.确定初始值,遍历顺序

    • dp[2] = 1,dp[1] = 1,dp[0] = 1 (dp[0] 和 dp[1] 实际上不符合题意,虽然赋值1 不影响结果)
    • i从3到n 遍历,j 从 1 到 i - 2 遍历
  • 4.根据上面三个步骤写代码:

public int integerBreak(int n) {int[] dp = new int[n + 1];//初始化赋值dp[2] = 1;for(int i = 3; i <= n; i++) {//从下标为2开始遍历for(int j = 1; j < i - 1; j++) {dp[i] = Math.max(dp[i], Math.max(j * (i - j), j * dp[i - j]));}}return dp[n];
}
6.LeetCode96. 不同的二叉搜索树

给你一个整数 n ,求恰由 n 个节点组成且节点值从 1n 互不相同的 二叉搜索树 有多少种?返回满足题意的二叉搜索树的种数。

示例 1:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

输入:n = 3
输出:5

这题确实不好解决,二叉搜索树的种树这个变量不好确定。需要以左右子树为基础进行考虑,下面引用代码随想录的思路:

dp[3],就是 元素1为头结点搜索树的数量 + 元素2为头结点搜索树的数量 + 元素3为头结点搜索树的数量

元素1为头结点搜索树的数量 = 右子树有2个元素的搜索树数量 * 左子树有0个元素的搜索树数量

元素2为头结点搜索树的数量 = 右子树有1个元素的搜索树数量 * 左子树有1个元素的搜索树数量

元素3为头结点搜索树的数量 = 右子树有0个元素的搜索树数量 * 左子树有2个元素的搜索树数量

有2个元素的搜索树数量就是dp[2]。

有1个元素的搜索树数量就是dp[1]。

有0个元素的搜索树数量就是dp[0]。

所以dp[3] = dp[2] * dp[0] + dp[1] * dp[1] + dp[0] * dp[2]

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

所以状态转移方程为 dp[i] += dp[j] * dp[i - j - 1];

初始值dp[0] = 1;dp[1] = 1,按照节点个数进行遍历。直接下出如下代码

public int numTrees(int n) {int[] dp = new int[n + 1];//初始化赋值dp[0] = 1;dp[1] = 1;for(int i = 2; i <= n; i++) {for(int j = 0; j < i; j++) {dp[i] += dp[j] * dp[i - j - 1];}}return dp[n];
}

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

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

相关文章

苍穹外卖-前端部分(持续更新中)

d 第二种&#xff1a;cmd中输入 vue ui进入图形化界面选择npm,vue2进行创建 先将创建的Vue框架导入Vsocde开发工具 然后ctrshiftp 输入npm 点击serve将项目启动 下这种写法跨域会报错&#xff1a; 解决方法&#xff1a; \ 注意 这种用法&#xff1a;&#xff08;不是单引号…

Android Handler完全解读

一&#xff0c;概述 Handler在Android中比较基础&#xff0c;本文笔者将对此机制做一个完全解读。读者可简单参考上述类图与时序图&#xff0c;便于后续理解。 二&#xff0c;源码解读 1&#xff0c;主线程伊始 众所周知&#xff0c;通过Zygote的fork方式&#xff0c;新创建…

SSH客户端 Termius for Mac 中文激活版

Termius for Mac是一款强大的终端和SSH客户端&#xff0c;为开发人员、系统管理员和网络工程师提供了全面的远程访问和管理工具。 软件下载&#xff1a;Termius for Mac 中文激活版下载 无论您是在使用Mac、Windows还是Linux系统&#xff0c;Termius都能提供出色的功能和用户体…

静态代理IP该如何助力Facebook多账号注册运营?

在Facebook运营中&#xff0c;充分利用静态代理IP是多账号运营的关键一环。通过合理运用静态代理IP&#xff0c;不仅可以提高账号安全性&#xff0c;还能有效应对Facebook的算法和限制。以下是这些关键点&#xff0c;可以帮助你了解如何运用静态代理IP进行Facebook多账号运营&a…

基于springboo校园社团信息管理系统

摘要 随着高校规模的扩大和学生社团活动的日益丰富多彩&#xff0c;校园社团信息管理成为一个备受关注的问题。为了更有效地组织、管理和推动校园社团的发展&#xff0c;本文设计并实现了一套基于Spring Boot的校园社团信息管理系统。本系统以实现社团信息的集中管理和高效运营…

使用dockers-compose搭建开源监控和可视化工具

简介 Prometheus 和 Grafana 是两个常用的开源监控和可视化工具。 Prometheus 是一个用于存储和查询时间序列数据的系统。它提供了用于监控和报警的数据收集、存储、查询和图形化展示能力。Prometheus 使用拉模型&#xff08;pull model&#xff09;&#xff0c;通过 HTTP 协议…

工具学习——使用OpenSmile提取音频特征

文章目录 OpenSmile介绍下载和安装提取特征格式转换特征提取尝试一正常使用手段常见的特征 使用Gnuplot可视化特征安装使用 总结 OpenSmile介绍 openSMILE&#xff08;open-source Speech and Music Interpretation by Large-space Extraction&#xff09;是一个开源工具包&am…

直流电机驱动(马达)

文章目录 一、介绍直流电机介绍电机驱动电路大功率器件直接驱动H桥驱动集成电路线路图 PWM介绍产生PWM的方法 二、实例1.呼吸灯案例2.直流电机调速 一、介绍直流电机 介绍 电机驱动电路 点击的负载较大&#xff0c;直接接在单片机I/O口上无法驱动&#xff0c;所以需要驱动电路…

Vite学习指南

那本课程都适合哪些人群呢&#xff1f; 想要学习前端工程化&#xff0c;在新项目中投入使用 Vite 构建工具的朋友 Webpack 转战到 Vite 的小伙伴 前端架构师们&#xff0c;可以充实自己的工具箱 当然如果你没有项目相关开发经验&#xff0c;也可以从本课程中受益&#xff0…

支付宝开通GPT4.0,最新经验分享

ChatGPT是由OpenAI开发的一种生成式对话模型&#xff0c;具有生成对话响应的能力。它是以GPT&#xff08;Generative Pre-trained Transformer&#xff09;为基础进行训练的&#xff0c;GPT是一种基于Transformer架构的预训练语言模型&#xff0c;被广泛用于各种自然语言处理任…

vue 样式隔离原理

日常写单文件组件时&#xff0c;会在style添加scoped属性&#xff0c;如<style scoped>&#xff0c;目的是为了隔离组件与组件之间的样式&#xff0c;如下面的例子&#xff1a; <template><p class"foo">这是foo</p><p class"bar&q…

C#从网址上读取json数据

需求&#xff1a;从客户给的网址中读取json格式的数据。 找了好多资料&#xff0c;都不太好使&#xff0c;看到了一篇很有帮助的文章。以下大部分内容和这篇找到的文章近似。太不容易了&#xff0c;同时也感谢这篇文章的作者心所欲。 https://www.cnblogs.com/zoujinhua/p/10…

数字图像处理(实践篇)三十四 OpenCV-Python绘制椭圆

目录 一 涉及的函数 二 实践 一 涉及的函数 cv2.ellipse(img,center,axes,angle,start_angle,end_angle,color,thickness) 参数: ①<

Future模式先给您提货单

Future模式是一种设计模式&#xff0c;用于在处理耗时操作时提高程序的响应性。 角色介绍: Main类: 负责向Host发出请求并获取数据的类。 Host类: 负责向请求返回FutureData的实例的类&#xff0c;起到调度的作用。 Data接口: 表示访问数据的方法的接口&#xff0c;由FutureD…

openGauss学习笔记-209 openGauss 数据库运维-常见故障定位案例-共享内存泄露问题

文章目录 openGauss学习笔记-209 openGauss 数据库运维-常见故障定位案例-共享内存泄露问题209.1 共享内存泄露问题209.1.1 问题现象209.1.2 原因分析209.1.3 处理方法 openGauss学习笔记-209 openGauss 数据库运维-常见故障定位案例-共享内存泄露问题 209.1 共享内存泄露问题…

算法沉淀——滑动窗口(leetcode真题剖析)

算法沉淀——滑动窗口 01.长度最小的子数组02.无重复字符的最长子串03.最大连续1的个数 III04.将 x 减到 0 的最小操作数05.水果成篮06.找到字符串中所有字母异位词07.串联所有单词的子串08.最小覆盖子串 滑动窗口算法是一种用于解决数组或列表中子数组或子序列问题的有效技巧。…

重装Windows系统出现Windows无法安装到这个磁盘,选中的磁盘采用GPT分区

文章目录 1.问题描述2.问题解决 1.问题描述 重装Windows系统时&#xff0c;出现Windows无法安装到这个磁盘&#xff0c;选中的磁盘采用GPT分区这个提示 2.问题解决 1.shiftF10&#xff0c;打开命令行 2.输入&#xff1a;diskpart (打开分区工具) 3.输入&#xff1a;list di…

elementplus Dialog 对话框设置距离页面顶部的距离

默认为 15vh&#xff0c;当弹窗过于高的时候&#xff0c;这个距离其实是不合适的 <el-dialogv-model"dialogVisible"title"Tips"width"30%":before-close"handleClose"top"6vh"><span>This is a message</s…

IDEA搭建JDK源码学习环境(可添加注释、修改、debug)

工程详见&#xff1a;https://github.com/wenpanwenpan/study-source-jdk1.8.0_281 1、找到src.zip和javafx-src.zip 找到你想要调试的JDK&#xff0c;笔者本地电脑上装了两个版本的JDK&#xff0c;这里以jdk1.8.0_281为例将JDK目录下的javafx-src.zip和src.zip两个压缩包进行…

详解SpringCloud微服务技术栈:ElasticSearch实践2——RestClient查询并处理文档

&#x1f468;‍&#x1f393;作者简介&#xff1a;一位大四、研0学生&#xff0c;正在努力准备大四暑假的实习 &#x1f30c;上期文章&#xff1a;详解SpringCloud微服务技术栈&#xff1a;ElasticSearch搜索结果处理&#xff08;排序、分页、高亮&#xff09; &#x1f4da;订…