dp_day6(从记忆化搜索(dfs)到递推(dp))

最长公共子序列

最长公共子序列

从最后一个元素开始思考,如果s[i]==t[j],毫无疑问,它们是公共的,直接考虑s[i-1],t[j-1]即可,如果不相等,就保留一个,舍去另一个,考虑s[i-1],t[j]与考虑s[i],t[j-1]两种情况的最大值即可,

记忆化搜索代码

class Solution {
public:
    vector>cache=vector>(1005,vector(1005,-1));
    int dfs(int i,int j,string&s,string&t)
    {
        if(i<0||j<0)
        return 0;
        if(cache[i][j]!=-1)
        {
            return cache[i][j];
        }
        int res;
        if(s[i]==t[j])
        {
            res=dfs(i-1,j-1,s,t)+1;
        }
        else
        {
            res=max(dfs(i-1,j,s,t),dfs(i,j-1,s,t));//选j不选i,选i不选j
        }
        cache[i][j]=res;
        return res;
    }
    int longestCommonSubsequence(string s, string t) {
        return dfs(s.size()-1,t.size()-1,s,t);
    }
};

递推代码 

class Solution {
public:
    int longestCommonSubsequence(string s, string t) {
        int n=s.size(),m=t.size();
        vector>f(n+5,vector(m+5,0));
        for(int i=0;i

编辑距离

编辑距离

如果s[i]==t[j],它们是相同的,考虑s[i-1],t[j-1]即可,如果不同,有三种方式,删除s的最后一个字母,即考虑,s[i-1],t[j],对a插入b的一个字母,相当于删除b,即考虑s[i],t[j-1],还可以替换,直接让这个位置的字母相同,即考虑,s[i-1],t[j-1],三种情况取个最小值,再加1.

记忆化搜索代码

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

递推代码

class Solution {
public:
    int minDistance(string word1, string word2) {
        int n=word1.size(),m=word2.size();
        int f[n+5][m+5];
        for(int i=0;i<=n;i++)f[i][0]=i;
        for(int j=0;j<=m;j++)f[0][j]=j;
        for(int i=0;i

最长严格递增子序列

最长严格递增子序列

以枚举选哪个作为切入点,而不是选或不选,枚举每个位置作为递增子序列的终点,取最大值.从这个终点再往前枚举,计算最长递增子序列,最后得到每个点作为终点的最长递增子序列长度,取所有点的最大值

记忆化搜索代码

class Solution {
public:
    vectorcache=vector(2505,-1);
    int dfs(int i,vector&nums)
    {
        if(cache[i]!=-1)
            return cache[i];
        int res=0;
        for(int j=0;j& nums) {
        int ans=0;
        for(int i=0;i

递推代码

class Solution {
public:
    int lengthOfLIS(vector& nums) {
        int n=nums.size(),f[n];
        for(int i=0;i

值得一说的是,将该数组去重并排序再与原数组求最长公共子序列也可以求得答案

你可能感兴趣的:(深度优先,算法,动态规划,c++,leetcode)