Day47 | 动态规划 :线性DP 最长公共子序列&&最长公共子数组

Day47 | 动态规划 :线性DP 最长公共子序列&&最长公共子数组

动态规划应该如何学习?-CSDN博客

本次题解参考自灵神的做法,大家也多多支持灵神的题解

最长公共子序列 编辑距离_哔哩哔哩_bilibili

动态规划学习:

1.思考回溯法(深度优先遍历)怎么写

注意要画树形结构图

2.转成记忆化搜索

看哪些地方是重复计算的,怎么用记忆化搜索给顶替掉这些重复计算

3.把记忆化搜索翻译成动态规划

基本就是1:1转换

文章目录

1143.最长公共子序列

[1143. 最长公共子序列 - 力扣(LeetCode)](https://leetcode.cn/problems/longest-common-subsequence/description/)\](https://leetcode.cn/problems/longest-increasing-subsequence/description/) #### 思路分析(子问题): 设两个字符串分别是s和t 对应的最后一个字母分别是x和y dfs(x,y)那就是s以x结尾,t以y结尾的两个字符串的最长公共子序列的长度了 那就有四种情况 1.选x这个字母也选y这个字母 2.不选x不选y 3.选x不选y 4.选y不选x 如果x==y,那肯定就是选x也选y,那肯定就是 dfs(x,y)=dfs(x-1,y-1)+1 如果说x!=y,那么就是剩下三种情况里面取一个最大值 ```cpp dfs(x,y)=max(dfs(x-1,y-1),dfs(x,y-1),dfs(x-1,y)) ``` 再仔细一看,其实 dfs(x,y-1),dfs(x-1,y)包含了dfs(x-1,y-1),所以不需要这个了 ```cpp dfs(x,y)=max(dfs(x,y-1),dfs(x-1,y)) ``` 不明白可以举例 dfs(x,y-1)=max(dfs(x-1,y-1),dfs(x,y-2)) 递归边界: 只要x或者y小于0,那么就说明有一个字符串已经没有字母可以选择了,那么就到达了边界。 #### 1.回溯 DFS **1.返回值和参数** i是上面x字母的下标,j是y的下标 dfs(i,j)那就是s以x结尾,t以y结尾的两个字符串的最长公共子序列的长度了 ```cpp int dfs(int i,int j,string &s,string &t) ``` **2.终止条件** 只要有一个小于0就说明没有字符可以选了 ```cpp if(i<0||j<0) return 0; ``` **3.本层逻辑** 相等就+1,不相等就三种选一种 ```cpp if(s[i]==t[j]) return dfs(i-1,j-1,s,t)+1; else return max(dfs(i-1,j,s,t),dfs(i,j-1,s,t)); ``` **完整代码:** 当然,这是超时的 ```cpp class Solution { public: int dfs(int i,int j,string &s,string &t) { if(i<0||j<0) return 0; if(s[i]==t[j]) return dfs(i-1,j-1,s,t)+1; else return max(dfs(i-1,j,s,t),dfs(i,j-1,s,t)); } int longestCommonSubsequence(string text1, string text2) { return dfs(text1.size()-1,text2.size()-1,text1,text2); } }; ``` ```cpp //lambda class Solution { public: int longestCommonSubsequence(string text1, string text2) { function dfs=[&](int i,int j)->int{ if(i<0||j<0) return 0; if(text1[i]==text2[j]) return dfs(i-1,j-1)+1; else return max(dfs(i-1,j),dfs(i,j-1)); }; return dfs(text1.size()-1,text2.size()-1); } }; ``` #### 2.记忆化搜索 就是搞一个哈希表dp,全都初始化为-1,每次返回前给哈希表dp赋值,碰到不是-1的那就是算过的,那就直接返回计算过的结果,不需要再次递归了 ```cpp class Solution { public: int dfs(int i,int j,string &s,string &t,vector> &dp) { if(i<0||j<0) return 0; if(dp[i][j]!=-1) return dp[i][j]; if(s[i]==t[j]) return dp[i][j]=dfs(i-1,j-1,s,t,dp)+1; else return dp[i][j]=max(dfs(i-1,j,s,t,dp),dfs(i,j-1,s,t,dp)); } int longestCommonSubsequence(string text1, string text2) { vector> dp(text1.size(),vector(text2.size(),-1)); return dfs(text1.size()-1,text2.size()-1,text1,text2,dp); } }; ``` ```cpp //lambda class Solution { public: int longestCommonSubsequence(string text1, string text2) { vector> dp(text1.size(),vector(text2.size(),-1)); function dfs=[&](int i,int j)->int{ if(i<0||j<0) return 0; if(dp[i][j]!=-1) return dp[i][j]; if(text1[i]==text2[j]) return dp[i][j]=dfs(i-1,j-1)+1; else return dp[i][j]=max(dfs(i-1,j),dfs(i,j-1)); }; return dfs(text1.size()-1,text2.size()-1); } }; ``` #### 3.1:1翻译为动态规划 **1.确定dp数组以及下标的含义** dp\[i\]\[j\]就是dfs(I,j) 下标从1开始,下标0记录的是上面if终止条件里面的(i\<0\|\|j\<0)的非法状态 **2.确定递推公式** 和dfs中也是对应的 ```cpp if(text1[i]==text2[j]) dp[i+1][j+1]=dp[i][j]+1; else dp[i+1][j+1]=max(dp[i][j+1],dp[i+1][j]); ``` **3.dp数组如何初始化** 都初始化为0即可 ```cpp vector> dp(text1.size()+1,vector(text2.size()+1,0)); ``` **4.确定遍历顺序** 从前往后遍历即可 ```cpp for(int i=0;i> dp(text1.size()+1,vector(text2.size()+1,0)); for(int i=0;i& nums1, vector& nums2) { vector> dp(nums1.size()+1,vector(nums2.size()+1,0)); int res=0; for(int i=0;i& nums1, vector& nums2) { vector> dp(nums1.size()+1,vector(nums2.size()+1,0)); for(int i=0;i

相关推荐
IT猿手2 小时前
基于强化学习 Q-learning 算法求解城市场景下无人机三维路径规划研究,提供完整MATLAB代码
神经网络·算法·matlab·人机交互·无人机·强化学习·无人机三维路径规划
万能程序员-传康Kk5 小时前
旅游推荐数据分析可视化系统算法
算法·数据分析·旅游
PXM的算法星球6 小时前
【并发编程基石】CAS无锁算法详解:原理、实现与应用场景
算法
ll7788116 小时前
C++学习之路,从0到精通的征途:继承
开发语言·数据结构·c++·学习·算法
烨然若神人~6 小时前
算法第十七天|654. 最大二叉树、617.合并二叉树、700.二叉搜索树中的搜索、98.验证二叉搜索树
算法
爱coding的橙子6 小时前
每日算法刷题Day2 5.10:leetcode数组1道题3种解法,用时40min
算法·leetcode
程序媛小盐7 小时前
贪心算法:最小生成树
算法·贪心算法·图论
Panesle7 小时前
分布式异步强化学习框架训练32B大模型:INTELLECT-2
人工智能·分布式·深度学习·算法·大模型
多多*7 小时前
算法竞赛相关 Java 二分模版
java·开发语言·数据结构·数据库·sql·算法·oracle
逐光沧海7 小时前
数据结构基础--蓝桥杯备考
数据结构·c++·算法·蓝桥杯