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

算法第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.lryc.cn/news/603215.html

相关文章:

  • 【图像处理基石】如何对遥感图像进行实例分割?
  • 小白学OpenCV系列1-图像处理基本操作
  • 在 Web3 时代通过自我主权合规重塑 KYC/AML
  • [SWPU2019]Web1
  • 链表反转中最常用的方法————三指针法
  • PHP云原生架构:容器化、Kubernetes与Serverless实践
  • redis【1】
  • 小程序视频播放,与父视图一致等样式设置
  • zama test
  • 百元级工业级核心板:明远智睿×瑞萨V2H,开启AIoT开发新纪元
  • PDF转Word免费工具!批量处理PDF压缩,合并, OCR识别, 去水印, 签名等全功能详解
  • 数据结构之时间复杂度
  • 前端css 的固定布局,流式布局,弹性布局,自适应布局,响应式布局
  • ZKmall开源商城中台架构实践:API 网关与服务治理如何撑起电商技术骨架
  • 在 PolkaVM 上用 Rust 实现 ERC20 合约的全流程开发指南
  • 接口自动化测试pytest框架
  • c++-list
  • 【VOS虚拟操作系统】未来之窗打包工具在前端资源优化中的应用与优势分析——仙盟创梦IDE
  • Redis内存使用耗尽情况分析
  • 40+个常用的Linux指令——下
  • 艾利特机器人:光伏机器人如何重塑清洁能源制造新格局
  • 【CDH】CDH环境中升级ZooKeeper的实战记录
  • 基于KMeans、AgglomerativeClustering、DBSCAN、PCA的聚类分析的区域经济差异研究
  • 【Linux知识】Linux Shell 脚本中的 `set -ex` 命令深度解析
  • 复现cacti的RCE(CVE-2022-46169)
  • Go 客户端玩转 ES|QL API 直连与 Mapping Helpers 实战详解
  • upload-labs靶场通关(1-12)
  • 服务器之光:Nginx--反向代理模块详解及演练
  • 图论:Bellman_ford算法
  • 《汇编语言:基于X86处理器》第10章 结构和宏(3)