代码随想录算法训练营第五十四天|LeetCode392.判断子序列、LeetCode115.不同的子序列

LeetCode 392 判断子序列

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

【解题思路】

  • 1.确定dp数组含义

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

  • 2.确定递推公式

    • s[i-1] == t[j-1]

      • 意思是找到了一个相同的字符

      • dp[i][j] = dp[i-1][j-1]+1

    • s[i-1] != t[j-1]

      • 意思是当前位置的两个字符串的字符不相同此时相当于t要删除元素

      • dp[i][j] = dp[i][j-1]

  • 3.初始化dp数组

    • 从递推公式可以看出dp[i][j]都是依赖于dp[i-1][j-1]推出来,因此需要初始化dp[0][0],dp[i][0]

      • 将他们都初始化为0

  • 4.确定遍历顺序

    • 由递推公式可以知道,遍历顺序一定是从上到下,从左到右

  • 5.举例推导dp数组

【解题步骤】

  • 1.定义两个变量存储题目给出的两个字符串长度,方便后续操作

  • 2.定义一个dp数组,长度为两个字符串的长度+1

  • 3.遍历字符串1,从1开始

    • 遍历字符串2,从2开始

      • 递推公式

  • 4.判断dp[length1][length2]的长度

    • 如果等于length1

      • 说明是子序列,return true

    • 如果不等于length2

      • 说明不是子序列,return false

【代码部分】

class Solution {
    public boolean isSubsequence(String s, String t) {
		int length1 = s.length();
		int length2 = t.length();
		int[][] dp = new int[length1+1][length2+1];
		for (int i = 1; i <= length1; i++) {
			for (int j = 1; j <= length2; j++) {
				if(s.charAt(i-1) == t.charAt(j-1)){
					dp[i][j] = dp[i-1][j-1] + 1;
				}else{
					dp[i][j] = dp[i][j-1];
				}
			}
		}
		if(dp[length1][length2] == length1){
			return true;
		}else{
			return false;
		}
    }
}

LeetCode 115 不同的子序列

题目链接: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]来匹配

        • dp[i][j] = dp[i-1][dp[j-1]

      • 不用s[i-1]来匹配

        • dp[i-1][j]

    • s[i-1] != t[j-1]

      • 此时不能用s[i-1]来匹配,模拟在s中删除这个元素

      • dp[i][j] = dp[i-1][j]

  • 3.初始化dp数组

    • 从递推公式可以看出dp[i][j]都是依赖于dp[i-1][j-1]推出来,因此需要初始化dp[0][j],dp[i][0]

      • dp[i][0]

        • 以i-1为结尾的s可以随便删除元素,出现空字符串的个数

        • dp[i][0] = 1

          • 也就是把以i-1为结尾的s,删除所有元素,出现空字符串的个数就是1

      • dp[0][j]

        • 空字符串s可以随便删除元素,出现以j-1为结尾的字符串t的个数

        • dp[0][j] = 0

          • s无论如何也变成不了t

      • dp[0][0]

        • dp[0][0] = 1

          • 空字符串s,可以删除0个元素,变成空字符串t

  • 4.确定遍历顺序

    • 由递推公式可以知道,遍历顺序一定是从上到下,从左到右

  • 5.举例推导dp数组

【解题步骤】

  • 1.定义一个dp数组,长度为两个字符串的长度+1

  • 3.遍历字符串s

    • 将dp[i][0]初始化为1

  • 4.遍历字符串s

    • 遍历字符串t

      • 如果两个字符串当前位置的元素相同

        • 递推公式1

      • 如果两个字符串当前位置的元素不同

        • 递推公式2

  • 5.return dp[s.length()][t.length()]

【代码部分】

class Solution {
    public int numDistinct(String s, String t) {
		int[][] dp = new int[s.length()+1][t.length()+1];
		for (int i = 0; i < s.length() + 1; i++) {
			dp[i][0] = 1;
		}
		for (int i = 1; i < s.length() +1; i++) {
			for (int j = 1; j < t.length()+1; 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];
				}

			}
		}
		return dp[s.length()][t.length()];
    }
}

  • 22
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值