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

Day49 | 动态规划 :线性DP 判断子序列两个字符串的删除操作

Day49 | 动态规划 :线性DP 判断子序列&&两个字符串的删除操作

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

动态规划学习:

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

注意要画树形结构图

2.转成记忆化搜索

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

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

基本就是1:1转换

文章目录

  • Day49 | 动态规划 :线性DP 判断子序列&&两个字符串的删除操作
    • 392.判断子序列
      • 思路分析(子问题):
      • 递归边界
      • 1.回溯
      • 2.记忆化搜索
      • 3.动态规划
    • 583.两个字符串的删除操作
      • 思路分析(子问题):
      • 1.回溯
      • 2.记忆化搜索
      • 3.动态规划

392.判断子序列

392. 判断子序列 - 力扣(LeetCode)

思路分析(子问题):

就是昨天的编辑距离的删除操作Day48 | 动态规划 :线性DP 编辑距离-CSDN博客

dfs(x,y)就是s的前x个字符是不是t的前y个字符的子序列,是返回true,不是返回false

x为s的下标,y为t的下标

还是看选或不选s[x]和t[y]

1.如果s[x]==t[y]

那就选s[x]和t[y]

返回dfs(x-1,y-1),继续递归下面的,即

dfs(x,y)=dfs(x-1,y-1)

也可以理解为当前的s[x]和t[y]对结果没有影响

2.如果s[x]!=t[y]

那就是删除掉t[y]看t剩下的部分包不包含s

dfs(x,y)=dfs(x,y-1)

递归边界

如果s为空串,那一定是t的子序列,返回true

如果t为空串,那s不管怎么样都不会是t的子序列,返回false

1.回溯

class Solution {
public:
    bool dfs(int i,int j,string &s,string &t)
    {
        if(i<0)
            return true;
        if(j<0)
            return false;
        if(s[i]==t[j])
            return dfs(i-1,j-1,s,t);
        else
            return dfs(i,j-1,s,t);
    }
    bool isSubsequence(string s, string t) {
        return dfs(s.size()-1,t.size()-1,s,t);
    }
};

2.记忆化搜索

就是搞一个哈希表dp,全都初始化为-1,每次返回前给哈希表dp赋值,碰到不是-1的那就是算过的,那就直接返回计算过的结果,不需要再次递归了

class Solution {
public:
    bool dfs(int i,int j,string &s,string &t,vector<vector<int>> &dp)
    {
        if(i<0)
            return true;
        if(j<0)
            return false;
        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);
        else
            return dp[i][j]=dfs(i,j-1,s,t,dp);
    }
    bool isSubsequence(string s, string t) {
        vector<vector<int>> dp(s.size(),vector<int>(t.size(),-1));
        return dfs(s.size()-1,t.size()-1,s,t,dp);
    }
};

3.动态规划

注意我们的i=0和j=0是表示的dfs中i<0和j<0非法的状态,即s为空串或者t为空串,对应的是递归边界

所以dp数组的下标从1开始记录答案

class Solution {
public:
    bool isSubsequence(string s, string t) {
        vector<vector<bool>> dp(s.size()+1,vector<bool>(t.size()+1,false));
        for(int i=0;i<=t.size();i++)
            dp[0][i]=true;
        for(int i=0;i<s.size();i++)
            for(int j=0;j<t.size();j++)
                if(s[i]==t[j])
                    dp[i+1][j+1]=dp[i][j];
                else    
                    dp[i+1][j+1]=dp[i+1][j];
        return dp[s.size()][t.size()];
    }
};

583.两个字符串的删除操作

583. 两个字符串的删除操作 - 力扣(LeetCode)

思路分析(子问题):

就是昨天的编辑距离的删除操作Day48 | 动态规划 :线性DP 编辑距离-CSDN博客

//相等不用删		
if(s[i]==t[j])
	return dfs(i-1,j-1,s,t);
//不相等
else
	return min(dfs(i-1,j,s,t),dfs(i,j-1,s,t))+1;
//               删s的            删t的
//两个里面搞一个最小值最后再把删除这一步的步数1加上搞定

仅仅是去掉了替换操作,剩下的代码都一样的,这里不做过多的解释了

1.回溯

class Solution {
public:
    int dfs(int i,int j,string& s,string &t)
    {
        if(i<0)
            return j+1;
        if(j<0)
            return i+1;
        if(s[i]==t[j])
            return dfs(i-1,j-1,s,t);
        else
            return min(dfs(i-1,j,s,t),dfs(i,j-1,s,t))+1;
    }
    int minDistance(string word1, string word2) {
        return dfs(word1.size()-1,word2.size()-1,word1,word2);        
    }
};

2.记忆化搜索

就是搞一个哈希表dp,全都初始化为-1,每次返回前给哈希表dp赋值,碰到不是-1的那就是算过的,那就直接返回计算过的结果,不需要再次递归了

class Solution {
public:
    int dfs(int i,int j,string& s,string &t,vector<vector<int>> &dp)
    {
        if(i<0)
            return j+1;
        if(j<0)
            return i+1;
        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);
        else
            return dp[i][j]=min(dfs(i-1,j,s,t,dp),dfs(i,j-1,s,t,dp))+1;
    }
    int minDistance(string word1, string word2) {
        vector<vector<int>> dp(word1.size(),vector<int>(word2.size(),-1));
        return dfs(word1.size()-1,word2.size()-1,word1,word2,dp);        
    }
};

3.动态规划

注意我们的i=0和j=0是表示的dfs中i<0和j<0非法的状态,即s为空串或者t为空串,对应的是递归边界

所以dp数组的下标从1开始记录答案

class Solution {
public:
    int minDistance(string word1, string word2) {
        vector<vector<int>> dp(word1.size()+1,vector<int>(word2.size()+1,0));
        for(int i=0;i<=word2.size();i++)
            dp[0][i]=i;
        for(int i=0;i<=word1.size();i++)
            dp[i][0]=i;
        for(int i=0;i<word1.size();i++)
            for(int j=0;j<word2.size();j++)
                if(word1[i]==word2[j])
                    dp[i+1][j+1]=dp[i][j];
                else
                    dp[i+1][j+1]=min(dp[i+1][j],dp[i][j+1])+1;
        return dp[word1.size()][word2.size()];        
    }
};

http://www.kler.cn/a/412761.html

相关文章:

  • 自动驾驶目标检测融合全貌
  • 极狐GitLab 17.6 正式发布几十项与 DevSecOps 相关的功能【四】
  • vue3typescript,shims-vue.d.ts中declare module的vue声明
  • 使用mingw+CMake在Windows平台编译OpenCV
  • Golang面经
  • Python绘制太极八卦
  • mini-spring源码分析
  • ASPICE 4.0在汽车行业软件开发中的广泛应用与深远影响
  • Hadoop Namenode与Resourcemanager高可用搭建教程
  • 微积分复习笔记 Calculus Volume 1 - 6.8 Exponential Growth and Decay
  • go聊天项目4-显示用户列表
  • 比特币安全机制与交易验证体系:私钥、公钥与防伪防篡改的深度解析
  • 如何安全高效地打开和管理动态链接库(DLL)?系统提示dll丢失问题的多种有效修复指南
  • vue 使用el-button 如何实现多个button 单选
  • maven 工具 clean、compile、package、install、deploy 常用命令使用区别
  • 非常简单实用的前后端分离项目-仓库管理系统(Springboot+Vue)part 2
  • 大数据新视界 -- Hive 查询性能优化:索引技术的巧妙运用(下)(6/ 30)
  • [kafka] 基础知识
  • 第21周:机器学习
  • 动静分离具体是怎么实现的?
  • 李宏毅机器学习课程知识点摘要(14-18集)
  • ffplay音视频同步处理
  • 突破Zustand的局限性:与React ContentAPI搭配使用
  • 人工智能零基础入门学习笔记
  • 小程序租赁系统开发的优势与应用解析
  • ES6 、ESNext 规范、编译工具babel