当前位置: 首页 > web >正文

算法第29天|动态规划dp2:不同路径、不同路径Ⅱ、整数拆分、不同的二叉搜索树

今日总结:

        1、动态规划的五部曲:

                (1)确定动态规划数组dp[]的含义,确定dp[]数组的下标的含义

                (2)确定动态规划的递推公式

                (3)确定动态规划的初始化条件

                (4)确定动态规划的传播方向

                (5)举例论证递推公式的正确

        2、不同路径Ⅱ(需要重新思考)

                要注意障碍所在的多种位置:第一行第一列、起点终点、普通中间网格

        3、整数拆分(需要重新思考)

                注意对于整数差分获得乘积的最大的几种情况

                        1、拆分成两个后的乘积就是最大值

                        2、拆分成两个后,还需要对第二个数进行拆分

                遍历的时候,其实将j遍历到i/2即可,因为剩余的已经相当于遍历过了

不同路径

题目链接:62. 不同路径 - 力扣(LeetCode)

代码随想录

整体思路:

        从左上到右下:所有的位置(i,j)只能通过向下移动、向右移动,进行到达,所以位置(i.j)与之前状态(i-1,j),(i,j-1)相关,是动态规划的问题。

        1、确定动态规划的dp数组含义以及下标含义

                dp[i][j]的含义是到达当前位置有多少条路径

                i是横坐标,j是纵坐标

        2、确定动态规划的递推公式(状态转移方程)

                dp[i][j] = dp[i-1][j]+dp[i][j-1]

        3、确定动态规划的初始化条件

                可以通过图分析可知,在第一行第一列,都是一种路径

        4、确定动态规划的方向:

                从左向右,从上到下

        5、举例论证

                简单无需举例

整体代码:

class Solution {
public:int uniquePaths(int m, int n) {/*1、确定动态规划的dp数组含义以及下标含义dp[i][j]的含义是到达当前位置有多少条路径i是横坐标,j是纵坐标2、确定动态规划的递推公式(状态转移方程)dp[i][j] = dp[i-1][j]+dp[i][j-1]3、确定动态规划的初始化条件可以通过图分析可知,在第一行第一列,都是一种路径4、确定动态规划的方向左向右,从上到下5、举例论证简单无需举例*/vector<vector<int>>dp(m,vector<int>(n,0));//遍历dpfor(int i=0;i<m;i++){for(int j=0;j<n;j++){if(i==0||j==0){dp[i][j]=1;}else{dp[i][j] = dp[i-1][j] +dp[i][j-1];}}}return dp[m-1][n-1];}
};

不同路径Ⅱ

题目链接:63. 不同路径 II - 力扣(LeetCode)

代码随想录

整体思路:

        与上一个题类似,需要注意有障碍物

        1、障碍物在开始或者终点-->直接返回0

        2、障碍物在第一行、第一列,障碍物之后的位置(包含障碍物坐标)路径全部为0

        3、障碍物在中间的网格,该点的路径为0

        (没进行代码优化,但是结果正确)

整体代码:

class Solution {
public:int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {vector<vector<int>>dp(obstacleGrid.size(),vector<int>(obstacleGrid[0].size(),0));//定义dp数组//初始化//1、注意障碍物在起点、终点的情况if(obstacleGrid[0][0]==1||obstacleGrid[obstacleGrid.size()-1][obstacleGrid[0].size()-1]==1)return 0;//注意第一行、第一列正常应该是一条路径,但是如果出现了障碍,后边的网格的路径为0for(int i=0;i<obstacleGrid.size();i++)//遍历行,所以是第一列{if(obstacleGrid[i][0]==0){dp[i][0] =1;}else if(obstacleGrid[i][0]==1)break;}for(int j=0;j<obstacleGrid[0].size();j++){if(obstacleGrid[0][j]==0){dp[0][j]=1;}else if(obstacleGrid[0][j]==1){break;}}//遍历整个网格,从第二行第二列开始就行,因为第一行第一列初始化了for(int i=1;i<obstacleGrid.size();i++){for(int j=1;j<obstacleGrid[0].size();j++){if(obstacleGrid[i][j]==0)//说明不是障碍物{dp[i][j] = dp[i-1][j]+dp[i][j-1];}else if(obstacleGrid[i][j]==0)//可不写{dp[i][j] = 0;}}}return dp[obstacleGrid.size()-1][obstacleGrid[0].size()-1];//0,1}
};

整数拆分

题目链接:343. 整数拆分 - 力扣(LeetCode)

代码随想录

整体思路:

        目标:拆分的整数的乘积最大化

        dp数组的作用是将当前的元素与之前的状态相联系,

从1遍历到n,相当于拆分,将当前的拆分值与剩余值进行相乘,

        n=10

        j=1,j*9;对于9还可以继续拆,所以需要找到9的最大的拆分乘积进行记录

        j=2,j*8,对于8还可以继续拆,所以需要找到8的最大的查拆乘积分进行记录

。。。

        所以,对于一个数进行拆分,需要知道这个数之前的所有数的最大拆分,然后找到最大的值-->当前元素的值与之前元素的状态有关,可以使用动态规划dp

        (1)确定dp数组的含义、下标的含义

                dp数组表示当前数的最大拆分的乘积,下标表示当前元素

        (2)确定dp数组的迭代公式(状态转移方程)

                dp[i] = j*dp[i-j];dp[i-j]表示的是dp[i-j]的最大拆分乘积,之所以不需要对j进行拆分是因为j是遍历元素,所有的拆分项都在dp[i-j]中出现过

                同时要注意,dp[i]的获取还有一种情况,就是i-j本身就是最大值无需在进行拆分dp[i-j]

                dp[i] = max(dp[i],dp[i-j],(i-j)*j),

        (3)确定dp数组的初始化

                dp[0]=0,dp[1]=1,dp[2]=2;

        (4)确定dp数组的方向

                从小到n

        (5)举例论证

                无需举例

整体代码:

class Solution {
public:int integerBreak(int n) {//谨记dp数组表示当前元素的最大乘积,下标表示当前数组vector<int>dp(n+1,0);//注意要处理的是n而不是n-1dp[0]=0,dp[1]=1;for(int i=2;i<=n;i++)//遍历所有的dp数组{for(int j=1;j<i;j++)//通过遍历从0-i确定当前的最大dp[i]{//dp状态转移方程dp[i] = max(dp[i],max(j*dp[i-j],(i-j)*j));}}return dp[n];}
};

不同的二叉搜索树

题目链接:96. 不同的二叉搜索树 - 力扣(LeetCode)

代码随想录

整体思路:

整体代码:

http://www.xdnf.cn/news/16688.html

相关文章:

  • uipath数据写入excel的坑
  • Python 程序设计讲义(25):循环结构——嵌套循环
  • 《Spring Cloud Gateway 深度剖析:从核心原理到企业级实战》
  • WAIC 2025观察:昇腾助力AI融入多元化生活场景
  • 理解Transformer解码器
  • Github 连接救星,完全合规合法,无风险!
  • 操作系统-lecture2(操作系统结构)
  • 微服务 01
  • Objective-c 初阶——异常处理(try-catch)
  • Typecho handsome新增评论区QQ,抖音,b站等表情包
  • 用FunASR轻松实现音频转SRT字幕:完整脚本与解析
  • iOS仿写 —— 计算器
  • Python 程序设计讲义(28):字符串的用法——格式化字符串
  • [leetcode] 组合总和
  • 冒泡排序算法
  • Java中什么是类加载?类加载的过程?
  • bash变量名不能有连字符
  • 【Redis实现基础的分布式锁及Lua脚本说明】
  • 爬虫逆向之瑞数五案例:某某医学院(补环境,联调)
  • Makefile 快速入门指南
  • 嵌入式第十四课!!!指针在字符数组的应用与数组指针
  • JavaWeb 入门:CSS 基础与实战详解(Java 开发者视角)
  • DataParallel (DP) DistributedDataParallel (DDP)
  • JavaWeb学习打卡18(JDBC案例详解)
  • [leetcode] 电话号码的排列组合
  • CSRF漏洞原理
  • CentOS7 安装和配置教程
  • USRP X410 X440 5G及未来通信技术的非地面网络(NTN)
  • Matplotlib(三)- 图表辅助元素
  • 经典算法题解析:从思路到实现,掌握核心编程思维