• 代码随想录训练营day55, 编辑距离问题: 判断子序列, 不同的子序列


    判断子序列:

    编辑距离入门问题

    1. 数组定义: 表示以下标i-1为结尾的字符串s,和以下标j-1为结尾的字符串t,相同子序列的长度为dp[i][j]

    2. 递推公式:

      if (s[i - 1] == t[j - 1]), 说明t中找到了一个字符在s中也出现了, 那么dp[i-1][j-1] + 1

      if (s[i - 1] != t[j - 1]), 相当于t要删除元素,继续匹配, 删除元素就是dp[i][j-1]

    3. 初始化: 根据递推公式可以发现dp[0][0]和dp[i][0]是必须初始化的, 是为0的,可以省略

    4. 最后判断长度是否相等

    细节统一:

    1. 遍历终止条件: 由于本题设定的是len-1的长度, 所以遍历完要=len
    2. 最后return 条件: 之前的dp数组定义是xxx位置, 现在是xxx长度, 所以有所不同
    1. class Solution {
    2. public boolean isSubsequence(String s, String t) {
    3. int len1 = s.length();
    4. int len2 = t.length();
    5. int[][] dp = new int[len1 + 1][len2 + 1];
    6. //直接开始遍历, 注意两个初始化定义是i-1;j-1, 所以<=
    7. for(int i = 1; i <= len1; i++){
    8. for(int j = 1; j <= len2; j++){
    9. //这里有两种情况
    10. //如果相等就+1
    11. if(s.charAt(i - 1) == t.charAt(j - 1)){
    12. dp[i][j] = dp[i - 1][j - 1] + 1;
    13. } else {
    14. //否则就得把t数组减一个
    15. dp[i][j] = dp[i][j - 1];
    16. }
    17. }
    18. }
    19. //最后判断一下数组长度是不是一模一样
    20. //由于定义, 这里不是len1-1
    21. if(dp[len1][len2] == len1){
    22. return true;
    23. } else {
    24. return false;
    25. }
    26. }
    27. }

    双指针解法:

    1. class Solution {
    2. public boolean isSubsequence(String s, String t) {
    3. int len1 = s.length();
    4. int len2 = t.length();
    5. int i = 0, j = 0;
    6. while(i < len1 && j < len2){
    7. if(s.charAt(i) == t.charAt(j)){
    8. //i最后用来判断是否成功移动到s的末尾了
    9. i++;
    10. }
    11. //j一直向前移动
    12. j++;
    13. }
    14. return i == len1;
    15. }
    16. }

    不同的子序列

    (这一题和上一题s和t反过来了, 现在t是子序列)

    给两个字符串, 计算s的子序列中t出现的个数(有多少种方式可以获得子序列)

    1. 数组定义: 以i-1为结尾的s子序列中出现以j-1为结尾的t的个数为dp[i][j]
    2. 递推公式:
      1. 如果相等: 也有两种情况, 因为可以有不同的组合来获得t(所以j固定)
        1. 所以就是dp[i-1][j-1] + dp[i-1][j]
      2. 如果不相等: 那就还是dp[i-1][j], (现在的j是子序列哦)
    3. 初始化: dp[i][0]表示, 以i-1为结尾的s, 同时子序列是空的, 所以是1(删除所有元素之和, 剩下的匹配[0]的个数还是1), dp[0][j]就肯定是0了(同样可以忽略)
    4. 遍历顺序: 仍然是从左上角开始
    1. class Solution {
    2. public int numDistinct(String s, String t) {
    3. int len1 = s.length();
    4. int len2 = t.length();
    5. int[][] dp = new int[len1 + 1][len2 + 1];
    6. //初始化先, 这里是初始化[i][0]; 下面初始化[0][j]可以忽略
    7. for(int i = 0; i <= len1; i++){
    8. dp[i][0] = 1;
    9. }
    10. //开始遍历
    11. for(int i = 1; i <= len1; i++){
    12. for(int j = 1; j <= len2; j++){
    13. //如果相等, 那么加上两种情况的组合个数
    14. if(s.charAt(i - 1) == t.charAt(j - 1)){
    15. dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j];
    16. } else {
    17. //不相等, 那么s-1继续找
    18. dp[i][j] = dp[i - 1][j];
    19. }
    20. }
    21. }
    22. return dp[len1][len2];
    23. }
    24. }

  • 相关阅读:
    [附源码]计算机毕业设计校园运动会管理系统Springboot程序
    这是JWT 简单使用
    怎么把自己写的组件发布到npm官方仓库??
    密评必备网站汇总
    作为一个普通人学习算法的经验分享
    字符串常用方法,想要的这儿都有
    js -- 跨域问题
    休闲娱乐 - 挂耳咖啡
    Spring源码学习笔记9——构造器注入及其循环依赖
    论文详解 GLENet 增强型3D目标检测网络
  • 原文地址:https://blog.csdn.net/Southside3amurai/article/details/128196186