代码随想录笔记_动态规划_392判断子序列

代码随想录算法训练营day55|392.判断子序列 |115.不同的子序列 t[j - 1]),此时相当于t要删除元素,t如果把当前元素t[j - 1]删除,那么。][j]表示以下标i-1为结尾的字符串s和以下标j-1为结尾的字符串t 相同子序列的长度,所以如果。表示以下标i-1为结尾的字符串s,和以下标j-1为结尾的字符串t,相同子序列的长度为。与 字符串s的长度相同说明:s与t的最长相同子序列就是s,那么s 就是 t 的子序列。一定都是1,因为也就是把以i-1为结尾的s,删除所有元素,出现空字符串的个数就是1。:以i-1为结尾的s子序列中出现以j-1为结尾的t的个数为。 阅读详情

代码随想录笔记_动态规划

代码随想录二刷笔记记录

LC392.判断子序列


题目

子序列问题

给定字符串 s 和 t ,判断 s 是否为 t 的子序列。

字符串的一个子序列是原始字符串删除一些(也可以不删除)字符而不改变剩余字符相对位置形成的新字符串。(例如,"ace"是"abcde"的一个子序列,而"aec"不是)。

示例 1:

输入:s = “abc”, t = “ahbgdc”
输出:true

示例 2:

输入:s = “axc”, t = “ahbgdc”
输出:false

提示:

0 <= s.length <= 100
0 <= t.length <= 10^4
两个字符串都只由小写字符组成。


思路分析

思路

思路:本题思路与LC1143一样,都是判断字符串A是否是字符串B的子串。即子序列问题,易想动态规划。当然,本题也可以使用双指针。

动态规划五部曲

1.确定dp数组及其下标的含义

dp[i][j] : 表示长度为 [0,i-1]  s 和长度为 [0,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 个字符不相等时,从s[i-1,j-2],t[i-2,j-1]中取目前最长子序列的长度

dp[i][j] = Max(dp[i-1][j],dp[i][j-1]);

但这里可以优化,因为我们只需要判断是否存在子串,返回值为 boolean。因此,只需要最终的dp数组结果即可,不用更新列。具体见5.推演分析,这里先给出更新后的递推公式

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

3.初始化

因为 dp[i][0] 和 dp[0][j] 都是没有意义的,赋值为0即可
本题返回值为boolean,因此二维数组初始化为 0即可。

4.遍历顺序

根据递推公式可知,从前往后遍历

for (int i = 1; i <= lenA; i++) {
    for (int j = 1; j <= lenB; 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];
         }
     }
}

5.推演分析

以 s = “abc”, t = “ahbgdc” 为例

沿用 LC1143 的方法,进行推演分析,同时更新行列,则有
请添加图片描述
根据本题只需要更新行,不需要更新列的情况,推演后得
请添加图片描述


代码实现

完整代码实现

public boolean isSubsequence(String s, String t) {
        int lenA = s.length();
        int lenB = t.length();
        //初始化
        int[][] dp = new int[lenA + 1][lenB + 1];
        //遍历
        for (int i = 1; i <= lenA; i++) {
            for (int j = 1; j <= lenB; j++) {
                if (s.charAt(i-1) == t.charAt(j-1)){
                    dp[i][j] = dp[i-1][j-1] + 1;
                }else {
                    //推演1的实现
//                    dp[i][j] = Math.max(dp[i-1][j],dp[i][j-1]);
                    //推演2
                    dp[i][j] = dp[i][j-1];
                }
            }
        }
        if (dp[lenA][lenB] == lenA){
            return true;
        }
        return false;
    }

【Day58】代码随想录动态规划_392判断子序列_115不同子序列 所以当s[i-1] == t[j-1]时候,dp[i][j]肯定包含dp[i-1][j-1]这是把s结尾的i-1和t结尾的j-1去除,是否可以加上呢?首先我想到用二维的dp数组,行表示字符串s,列表示字符串t,dp[i][j]表示s [0, i-1]与t [0, j-1]是否是子序列,dp的类型是bool类型,初始化全为false,但是由于bool类型只能表示是 或者 不是,没办法提供额外信息,所以在更新dp的时候,递推公式是dp[i][j] = dp[i-1][j-1]; 阅读详情

相关推荐

动态规划|392.判断子序列

day55 算是老朋友了,用动归解题~

Talking999的博客 1058

代码随想录刷题笔记 Day 58 | 判断子序列 No.392 | 不同的子序列 No.115

本题是要查询 s 中有多少种方法可以得到 t,比如第一个案例 s = “rabbbit”, t = “rabbit”,首先来考虑如何划分这个子问题:既然我去查询 s 有多少种方法可以得到 “rabbit” 比较困难,那能否先去找方法得到 “t” 呢?在这种情况下,你会怎样改变代码?s 的前 m 个元素和 t 的前 n 个元素的公共子序列的长度,是可以通过 m - 1 和 n - 1 组成的公共子序列的长度推出的。表示 s 的钱 i - 1 个元素和 t 的前 j - 1 个元素构成的最长公共子序列的大小。

kkq的博客 1251

代码随想录算法训练营第56天|392.判断子序列、115.不同的子序列

2.if (s[i - 1] == t[j - 1]),那么dp[i][j] = dp[i - 1][j - 1] + 1;= t[j - 1]),此时相当于t要删除元素,t如果把当前元素t[j - 1]删除,那么dp[i][j] 的数值就是 看s[i - 1]与 t[j - 2]的比较结果了,即:dp[i][j] = dp[i][j - 1];所以当s[i - 1] 与 t[j - 1]相等时,dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j];

wx_xxxx的博客 807

代码随想录算法训练营DAY52|C++动态规划Part13|392.判断子序列、115.不同的子序列

KMP算法求的是连续序列,本题中仅仅是来求子序列字符串的一个 子序列 是指,通过删除一些(也可以不删除)字符且不干扰剩余字符相对位置所组成的新字符串。一定都是1,因为也就是把以i-1为结尾的s,删除所有元素,出现空字符串的个数就是1。,也就是说,我们的当前格子需要左上方格子和左边格子才能推导出来。那必然是1,因为空字符串s可以删除0个元素,变成空字符串t。这一类问题,基本是要分析两种情况,这里是跟上一题一样的。根据递推公式来的,从上到下,从左到右。,如果遇到不相同的元素,字符串

糖炒栗子 1176

代码随想录算法训练营第day54|392.判断子序列 、 115.不同的子序列

t[j - 1]),此时相当于t要删除元素,t如果把当前元素t[j - 1]删除,那么dp[i][j] 的数值就是 看s[i - 1]与 t[j - 2]的比较结果了,即:dp[i][j] = dp[i][j - 1];if (s[i - 1] == t[j - 1]),那么dp[i][j] = dp[i - 1][j - 1] + 1;所以当s[i - 1] 与 t[j - 1]相等时,dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j];

qq_60513199的博客 1084

leetcode-代码随想录-动态规划-392判断子序列

如果有大量输入的 S,称作 S1, S2, …, Sk 其中 k >= 10亿,你需要依次检查它们是否为 T 的子序列。dp[i][j]都是依赖于dp[i - 1][j - 1] 和 dp[i][j - 1],所以dp[0][0]和dp[i][0]是一定要初始化的。dp[i][j] 表示以下标i-1为结尾的字符串s,和以下标j-1为结尾的字符串t,相同子序列的长度为dp[i][j]。字符串的一个子序列是原始字符串删除一些(也可以不删除)字符而不改变剩余字符相对位置形成的新字符串。:双重循环,都从前往后。

luckyme_的博客 919

代码随想录55——动态规划392判断子序列、115不同的子序列

如下图所示。如果要是定义的。

qq_42731705的博客 380

代码随想录算法训练营第54天| Leetcode 392.判断子序列、Leetcode 115.不同的子序列

最后一道题的递推公式不太好理解,我感觉我并没有理解透彻。最后,如果文章有错误,请在评论区或私信指出,让我们共同进步!

Camellia__Wang的博客 1075

【Day58】代码随想录动态规划part15(编辑距离系列问题)——判断子序列、不同的子序列

dp[i][j]:表示以i-1为结尾的s中以j-1为结尾的t的个数。

格子格鸽的个人博客 1110

代码随想录算法训练营第44动态规划part11 | 题目:1143.最长公共子序列1035.不相交的线、53. 最大子序和、392.判断子序列

if (s[i - 1] == t[j - 1]),那么dp[i][j] = dp[i - 1][j - 1] + 1;= t[j - 1]),此时相当于t要删除元素,t如果把当前元素t[j - 1]删除,那么dp[i][j] 的数值就是 看s[i - 1]与 t[j - 2]的比较结果了,即:dp[i][j] = dp[i][j - 1];从递推公式可以看出dp[i][j]都是依赖于dp[i - 1][j - 1] 和 dp[i][j - 1],所以dp[0][0]和dp[i][0]是一定要初始化的。

weixin_51303606的博客 1237

代码随想录算法训练营第58天|动态规划part15|392.判断子序列、115.不同的子序列

思路:(这道题也可以用双指针的思路来实现,时间复杂度也是O(n))这道题应该算是编辑距离的入门题目,因为从题意中我们也可以发现,只需要计算删除的情况,不用考虑增加和替换的情况。所以掌握本题的动态规划解法是对后面要讲解的编辑距离的题目打下基础。dp[i][j] 表示以下标i-1为结尾的字符串s,和以下标j-1为结尾的字符串t,相同子序列的长度为dp[i][j]。注意这里是判断s是否为t的子序列。即t的长度是大于等于s的。

gengjiahao的博客 740

代码随想录NO50 |动态规划_leetcode 392.判断子序列 115.不同的子序列

动态规划_leetcode 392.判断子序列 115.不同的子序列

Rocket,Qian的博客 445

代码随想录Day55|392.判断子序列、115.不同的子序列

392.判断子序列、115.不同的子序列

weixin_46620779的博客 653

代码随想录-算法训练营day54(动态规划15:判断子序列,不同的子序列)

动态规划15:子序列

weixin_61931006的博客 747

代码随想录算法训练营第55天|392.判断子序列,115.不同的子序列

使用双指针法很简单,这里采用动态规划来解决。

MITWCQ的博客 658

代码随想录Day58 | 392.判断子序列 115.不同的子序列

Day58

sRiddle的博客 543

代码随想录day55|392.判断子序列|115.不同的子序列|Golang

笔记

weixin_42161901的博客 427

代码随想录算法训练营第五十五天| 392.判断子序列,115.不同的子序列

t[j - 1]),此时相当于t要删除元素,t如果把当前元素t[j - 1]删除,那么dp[i][j] 的数值就是 看s[i - 1]与 t[j - 2]的比较结果了,即:dp[i][j] = dp[i][j - 1];其实这里 大家可以发现和。

qq_42973684的博客 994
上一篇: 代码随想录笔记_动态规划_53最大子数组和
下一篇: Redis学习笔记1_数据类型
Erik_Won
博客等级 码龄7年 10粉丝 · 90原创
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值