Leetcode:392. 判断子序列、115. 不同的子序列(C++)

目录

392. 判断子序列

题目描述:

实现代码与解析:

双指针

原理思路:

动态规划:

原理思路:

115. 不同的子序列

题目描述:

实现代码与解析:

动态规划

原理思路:


392. 判断子序列

题目描述:

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

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

进阶:

如果有大量输入的 S,称作 S1, S2, ... , Sk 其中 k >= 10亿,你需要依次检查它们是否为 T 的子序列。在这种情况下,你会怎样改变代码?

示例 1:

输入:s = "abc", t = "ahbgdc"
输出:true

示例 2:

输入:s = "axc", t = "ahbgdc"
输出:false

提示:

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

实现代码与解析:

双指针

class Solution {
public:
    bool isSubsequence(string s, string t) {
        int i = 0, j = 0;
        while(i < s.size() && j < t.size())
        {
            if (s[i] == t[j])
            {
                i++;
                j++;
            }
            else j++;
        }
        if (i == s.size()) return true;
        else return false;
    }
};

原理思路:

        双指针,较简单。

动态规划:

class Solution {
public:
    bool isSubsequence(string s, string t) {
       
       vector<vector<int>> f(s.size() + 1, vector<int>(t.size() + 1, 0));

        for (int i = 1; i <= s.size(); i++)
            for (int j = 1; j <= t.size(); j++)
            {
                if (s[i - 1] == t[j - 1]) f[i][j] = f[i - 1][j - 1] + 1;
                else f[i][j] = max(f[i - 1][j], f[i][j - 1]);
            }
            if (f[s.size()][t.size()] == s.size()) return true;
            return false;

    }
};

原理思路:

        与求两字符串最长公共子序列相同, 只不过这里是判断一个字符串是不是另一个字符串的子序列而已。dp[i][j]数组含义为s中前 i - 1,t中 j - 1 前(包含 j - 1)的最长公共子序列。

        所以

else f[i][j] = max(f[i - 1][j], f[i][j - 1]);

也可以改为:

else f[i][j] = f[i][j - 1];

        这时dp数组的含义就变为了s中以 i - 1为结尾串和t中 j - 1 前(包含 j - 1)的最长公共子序列。也可以解决问题。

115. 不同的子序列

题目描述:

        给你两个字符串 s 和 t ,统计并返回在 s 的 子序列 中 t 出现的个数。

题目数据保证答案符合 32 位带符号整数范围。

示例 1:

输入:s = "rabbbit", t = "rabbit"
3
解释:
如下所示, 有 3 种可以从 s 中得到 "rabbit" 的方案。
rabbbit、rabbbit、rabbbit

示例 2:

输入:s = "babgbag", t = "bag"
输出5
解释:
如下所示, 有 5 种可以从 s 中得到 "bag" 的方案。 
babgbag、babgbag、babgbag、babgbag、babgbag

提示:

  • 1 <= s.length, t.length <= 1000
  • s 和 t 由英文字母组成

实现代码与解析:

动态规划

class Solution {
public:
    int numDistinct(string s, string t) {
        vector<vector<unsigned long long>> f(s.size() + 1, vector<unsigned long long>(t.size() + 1, 0));
        // 初始化
        for (int i = 0; i < s.size(); i++) f[i][0] = 1;

        for (int j = 1; j < t.size(); j++) f[0][j] = 0;

        for (int i = 1; i <= s.size(); i++)
            for (int j = 1; j <= t.size(); j++)
                if (s[i - 1] == t[j - 1]) f[i][j] = f[i - 1][j - 1] + f[i - 1][j];
                else f[i][j] = f[i - 1][j];
        
        return f[s.size()][t.size()];
    }
};

原理思路:

        沿用前一题的思想,我们dp[i][j]数组的含义为s的下标 i - 1(包含i - 1),t 中以 j  - 1结尾的串中公共子序列的个数。

        根据dp数组的含义写出递推式

·当 s[i-1] == t[j-1]时,f[ i ][ j ] = f[ i - 1 ][ j - 1] + f[ i - 1][ j ] ,两种情况,j 可以选择和 i 匹配,也可以选择不和 i 匹配和 i 前面的匹配,因为这里要计算个数嘛,所以要相加起来。

·当 s[i-1] != t[j-1] 时, f[ i ][ j ] = f[ i - 1][ j ], 既然不相等,那么只能选择和 i 前面的去匹配。 

        本题最重要的是dp数组的初始化

·当 j = 0 时,说明 t 为空,所以 s 中一个都不选才能为空这一种情况,所以赋值为1。

·当 i = 0 时,说明 s 为空,t 无论如何都不可能形成空,所以赋值为0。

·当 i 和 j 都 等于 0 时,显然也是 1。

        可以根据dp数组含义好好思考一下。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Cosmoshhhyyy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值