代码随想录LeetCode | day55&56 动态规划编辑问题回顾

目录

题目回顾

动态规划相关章节

动态规划五步法:

1.判断子序列

2.不同的子序列

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

4.编辑距离

总结


前沿:撰写博客的目的是为了再刷时回顾进一步完善,其次才是以教为学,所以如果有些博客写的较简陋,是为了保持进度不得已而为之,还请大家多多见谅。

预:看到题目后的思路和实现的代码。

见:参考答案展示。

感思:对比答案后的思考,与之前做过的题目是否有关联。

行:

(1)对于没做出来的题目,阅读答案后重新做一遍;

(2)下次做题可以尝试改善的方向;

(3)有助于理解的相关的题目

优先级:做题进度>学习&总结>默写回顾>做题数量

题目回顾

代码随想录LeetCode | day55&56 动态规划编辑问题回顾_第1张图片

 代码随想录LeetCode | day55&56 动态规划编辑问题回顾_第2张图片

动态规划相关章节

代码随想录刷LeetCode | day39 动态规划刷题回顾

代码随想录刷LeetCode | day41 动态规划刷题回顾

http://t.csdn.cn/9FPWN

动态规划五步法:

  1. 确定dp数组以及下标的含义
  2. 确定递推公式

  3. dp数组如何初始化

  4. 确定遍历顺序

  5. 举例推导dp数组

1.判断子序列

题目链接:392.判断子序列

一刷:

遍历当两个值相等时,记录长度+1,当长度等于子序列时跳出循环

最后判断记录长度是否等于子序列长度。

假设dp[i]表示遍历到i时,s是否为[0,i]的子序列,但做到后面发现不需要dp[i]就能做出来。

但动态规划一般都是计算长度or次数,自行增加新变量来判断是否满足条件。

class Solution {
    public boolean isSubsequence(String s, String t) {
        int lens = s.length();
        int lent = t.length();
        int dp = 0;
        int j = 0;
        for(int i = 0;i < lent && j < lens;i++){
            if(s.charAt(j) == t.charAt(i)){
                dp++;
                j++;
            }
        }
        return dp == lens ?true:false;
    }
}

2.不同的子序列

题目链接:115.不同的子序列

二刷:思路正确,小细节错误s.charAt(i-1) == st.charAt(j-1)

一刷:

dp[i][j]以下标i-1为结尾的字符串s,和以下标j-1为结尾的字符串t,相同子序列的次数为dp[i][j]。

ch[i] == ch[j] 相同则其次数等于:dp[i-1][j-1]和之前可能重复的子序列的次数dp[i-1][j]。

class Solution {
    public int numDistinct(String s, String t) {
        int lens = s.length();
        int lent = t.length();
        int[][] dp = new int[lens+1][lent+1];
        for(int i = 0;i <= lens;i++){
            dp[i][0] = 1;
        }
        for(int i = 1;i <= lens;i++){
            for(int j = 1;j <= lent && j<= i;j++){
                if(s.charAt(i-1) == t.charAt(j-1)){
                    dp[i][j] = dp[i-1][j-1]+dp[i-1][j];
                }else{
                    dp[i][j] = dp[i-1][j];
                }
                //System.out.println("i:"+i+",j:"+j+",dp:"+dp[i][j]);
            }
        }
        return dp[lens][lent];
    }
}

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

题目链接:583. 两个字符串的删除操作

二刷:不想再写黑板来笔画和用示例模拟,但还是要求自己做了,确实理清了思路。

为什么使用动态规划?计数and能够推导过程

dp[i][j]表示遍历到i,j 时使用最少的删除操作数

递推公式:需要删除or不需要删除两种情况

  1. word1[i] == word2[j] 时,则其不需要删除:dp[i][j] = dp[i-1][j-1];
  2. word1[i] != word2[j] 时,则需要删除,删除则有三种情况,三种情况中取最小。
    1. 变成dp[i-1][j-1],则需要删除新增的两个字符。
    2. 变成dp[i-1][j] or dp[i][j-1],则只需要删除一个字符。
class Solution {
    public int minDistance(String word1, String word2) {
        //dp[i][j] 不同即删,[i-1][j]+1\[i][j-1]+1\[i-1][j-1]+2
        int len1 = word1.length();
        int len2 = word2.length();
        int[][] dp = new int[len1+1][len2+1];
        for(int i = 0;i <= len1;i++){
            dp[i][0] = i;
        }
        for(int j = 0;j <= len2;j++){
            dp[0][j] = j;
        }
        for(int i = 1;i <= len1;i++){
            for(int j = 1;j <= len2;j++){
                if(word1.charAt(i-1) == word2.charAt(j-1)){
                    dp[i][j] = dp[i-1][j-1];
                }else{
                    dp[i][j] = Math.min(dp[i-1][j],Math.min(dp[i][j-1],dp[i-1][j-1]+1))+1;
                    //dp[i][j] = Math.min(dp[i-1][j],dp[i][j-1])+1;
                    //System.out.println(dp[i][j]+",-1:"+dp[i-1][j]+":"+dp[i][j-1]);
                }
            }
        }
        return dp[len1][len2];
    }
}

4.编辑距离

题目链接:72. 编辑距离

编辑能够删除、插入和修改,每次只能对一个字符操作。

word1[i] == word2[j]时,与上题“两个字符串的删除操作”情况相同:dp[i][j] = dp[i-1][j-1];

word1[i] != word2[j]时,则在下面两种情况中取最小。

  1. 删除和插入本质上是相同的,则能够直接套用“两个字符串的删除操作”。
    1. dp[i][j] = min(dp[i-1][j]+dp[i][j-1])+1;
  2. 修改则是这两道题的区别之处:其能够直接对当前比较字符修改其中一个,即满足。
    1. dp[i][j] = dp[i-1][j-1]+1;
class Solution {
    public int minDistance(String word1, String word2) {
        int len1 = word1.length();
        int len2 = word2.length();
        int[][] dp = new int[len1+1][len2+1];
        for(int i = 0;i <= len1;i++){
            dp[i][0] = i;
        }
        for(int i = 0;i <= len2;i++){
            dp[0][i] = i;
        }
        for(int i = 1;i <= len1;i++){
            for(int j = 1;j <= len2;j++){
                if(word1.charAt(i-1) == word2.charAt(j-1)){
                    dp[i][j] = dp[i-1][j-1];
                }else{
                    dp[i][j] = Math.min(dp[i-1][j],Math.min(dp[i][j-1],dp[i-1][j-1]))+1;
                }
            }
        }
        return dp[len1][len2];
    }
}

你可能感兴趣的:(动态规划,leetcode,算法)