• 代码随想录 Day46 动态规划14 LeetCode T392 判断子序列 T115 不同的子序列


    LeetCode T392 判断子序列 

    题目链接:392. 判断子序列 - 力扣(LeetCode)

    题目思路:

    本题有两种思路,第一个思路是使用双指针,第二个思路是使用动态规划,结尾笔者会附上两种方法的代码.

    1.双指针

    首先我们谈双指针的思路,就是让两个指针分别指向s和t字符串的开头,只要遇到相同字母,两者同时向后走一步,如果没有遇到字符相同,则只有t指针向后走,最后只要判断走完不管是s或者是t先走完,只要判断s对应的指针下标大小是否和其长度一样即可

    2.动态规划(和最长公共子序列基本一样)

    2.1 明确dp数组含义

    dp数组表示的是结尾为i-1和结尾为j-1的s和t字符串匹配的字符数量

    2.2 明确dp数组递推公式

    如果遇到相等就是dp[i][j] = dp[i-1][j-1] + 1

    不相等就是 dp[i][j] = dp[i-1][j] 

    2.3 初始化dp数组

    无需初始化

    2.4 明确遍历顺序

    顺序遍历即可

    2.5 打印dp数组排错

    题目代码:

    1. //动态规划
    2. class Solution {
    3. public boolean isSubsequence(String s, String t) {
    4. int len1 = s.length();
    5. int len2 = t.length();
    6. int[][] dp = new int[len1+1][len2+1];
    7. for(int i = 1;i<=len1;i++){
    8. char c1 = s.charAt(i-1);
    9. for(int j = 1;j<=len2;j++){
    10. char c2 = t.charAt(j-1);
    11. if(c1 == c2){
    12. dp[i][j] = dp[i-1][j-1]+1;
    13. }else{
    14. dp[i][j] = Math.max(dp[i-1][j],dp[i][j-1]);
    15. }
    16. }
    17. }
    18. if(dp[len1][len2] == len1){
    19. return true;
    20. }else{
    21. return false;
    22. }
    23. }
    24. }
    25. //双指针
    26. class Solution {
    27. public boolean isSubsequence(String s, String t) {
    28. int len1 = s.length();
    29. int len2 = t.length();
    30. int i = 0,j = 0;
    31. while(i
    32. if(s.charAt(i) == t.charAt(j)){
    33. i++;
    34. j++;
    35. }
    36. else{
    37. j++;
    38. }
    39. }
    40. return i == len1;
    41. }
    42. }

    LeetCode T115 不同的子序列

    题目链接:115. 不同的子序列 - 力扣(LeetCode)

    题目思路:

    1确定dp数组含义

    这里的dp[i][j]表示以i-1为结尾的s子序列中出现以j-1为结尾的t的个数为dp[i][j]。

    2.确定递推公式

    • s[i - 1] 与 t[j - 1]相等
    • s[i - 1] 与 t[j - 1] 不相等

    当s[i - 1] 与 t[j - 1]相等时,dp[i][j]可以有两部分组成。

    一部分是用s[i - 1]来匹配,那么个数为dp[i - 1][j - 1]。即不需要考虑当前s子串和t子串的最后一位字母,所以只需要 dp[i-1][j-1]。

    一部分是不用s[i - 1]来匹配,个数为dp[i - 1][j]。

    举例,假设s = 'rara',t = 'ra'

    这时候我们用最后一个a,那么其实s的最后一个a消掉,t的最后一个a也消掉,那么其实就是   dp[i-1][j-1]

    这个时候如果不用最后一个字母a,就是在前面''rar''看有没有''ra'',就是dp[i-1][j]

    当最后一个字母不同的时候,其实也不用考虑了,比如'rarb'这里b也用不上呀,只能向前看      dp[i-1][j]是否有满足条件的结果

    3.初始化dp数组

    dp[i][0] 表示:以i-1为结尾的s可以随便删除元素,出现空字符串的个数。

    那么dp[i][0]一定都是1,因为也就是把以i-1为结尾的s,删除所有元素,出现空字符串的个数就是1。

    4.确定遍历方式

    从前向后遍历,因为后者依赖前者产生

    5.打印数组排错

    题目代码:

    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. for(int i = 0;i1;i++){
    7. dp[i][0] = 1;
    8. }
    9. for(int i = 1;i<=len1;i++){
    10. char c1 = s.charAt(i-1);
    11. for(int j = 1;j<=len2;j++){
    12. char c2 = t.charAt(j-1);
    13. if(c1 == c2){
    14. dp[i][j] = dp[i-1][j-1] + dp[i-1][j];
    15. }else{
    16. dp[i][j] = dp[i-1][j];
    17. }
    18. }
    19. }
    20. return dp[len1][len2];
    21. }
    22. }

  • 相关阅读:
    NR modulation 1
    vue 使用crypto.js解密后,用JSON.parse转义报错非空白格解决办法
    金仓数据库 KingbaseGIS 使用手册(3. KGIS插件安装说明)
    大咖说·对话生态|当Confluent遇见云:实时流动的数据更有价值
    js加密进阶与搭建Node服务
    【MySQL初阶】索引
    Android 10 如何在通知栏下拉状态栏会暂停第三方应用播放视频
    如何获取视图 view 的字段名和字段类型
    GraphQL(8):与数据库结合示例
    在Ubuntu中设置中文输入法的步骤
  • 原文地址:https://blog.csdn.net/qiuqiushuibx/article/details/134423051