【LeetCode 面试经典150题】392. Is Subsequence 判断子序列

392. Is Subsequence

题目大意

Given two strings s and t, return true if s is a subsequence of t, or false otherwise.

A subsequence of a string is a new string that is formed from the original string by deleting some (can be none) of the characters without disturbing the relative positions of the remaining characters. (i.e., “ace” is a subsequence of “abcde” while “aec” is not).

中文释义

给定两个字符串 st,如果 st 的子序列,则返回 true,否则返回 false

字符串的子序列是指通过从原始字符串中删除一些(也可以不删除)字符,而不打乱剩余字符的相对位置形成的新字符串。(例如,“ace” 是 “abcde” 的一个子序列,而 “aec” 则不是)。

示例

Example 1:

Input: s = "abc", t = "ahbgdc"
Output: true

Example 2:

Input: s = "axc", t = "ahbgdc"
Output: false

限制条件

  • 0 <= s.length <= 100
  • 0 <= t.length <= 10^4
  • s and t consist only of lowercase English letters.

进阶问题

Follow up: Suppose there are lots of incoming s, say s1, s2, …, sk where k >= 10^9, and you want to check one by one to see if t has its subsequence. In this scenario, how would you change your code?

解题思路

方法

这个解决方案的目的是判断字符串 s 是否为字符串 t 的子序列。它主要使用了双指针技术来遍历两个字符串,并按照以下步骤执行:

  1. 初始化指针:使用两个指针 indexSindexT 分别指向字符串 st 的开始位置。

  2. 遍历字符串

    • 当两个指针都未达到各自字符串的末尾时,循环继续。
    • 在每次循环中,比较 s[indexS]t[indexT]
      • 如果它们相等,意味着在 t 中找到了 s 的当前字符,因此将 indexS 增加 1,移动到 s 的下一个字符。
      • 无论是否找到匹配,都将 indexT 增加 1,移动到 t 的下一个字符。
  3. 判断结果

    • 如果 indexS 等于 s 的长度,意味着 s 中的所有字符都按顺序在 t 中找到了,因此返回 true
    • 如果循环结束时 indexS 未达到 s 的末尾,意味着 s 不是 t 的子序列,因此返回 false

代码

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

进阶解题思路

方法

该解决方案使用动态规划来预处理字符串 t,以加速判断多个字符串 s 是否是 t 的子序列的过程。它主要分为两个步骤:

  1. 预处理 t

    • 创建一个二维数组 dp,其维度为 (n + 1) x 26,其中 n 是字符串 t 的长度。dp[i][j] 表示从字符串 t 的第 i 个位置开始往后第一次出现字符 j 的位置。
    • t 的末尾开始遍历,并为每个字符更新 dp 数组。对于每个位置 i 和每个可能的字符 j (az):
      • 如果 t[i] 等于字符 j,则 dp[i][j] = i
      • 否则,dp[i][j] = dp[i + 1][j],意味着 jt 中的下一个位置是从 i + 1 开始的。
  2. 检查 s 是否为 t 的子序列

    • s 设置一个指针 index,初始为 0。
    • 遍历 s 的每个字符。对于每个字符 c
      • 使用 dp 数组来更新 index,即 index = dp[index][c - 'a']
      • 如果 index 等于 n,表示 c 字符在 t 中不存在,因此 s 不是 t 的子序列,返回 false
      • 否则,递增 index,继续检查下一个字符。
    • 遍历结束后,如果没有返回 false,则表示 st 的子序列,返回 true

代码

class Solution {
public:
    bool isSubsequence(string s, string t) {
        int n = t.size();
        vector<vector<int>> dp(n + 1, vector<int>(26, n));

        // 预处理 t,填充 dp 数组
        for (int i = n - 1; i >= 0; i--) {
            for (int j = 0; j < 26; j++) {
                if (t[i] == 'a' + j)
                    dp[i][j] = i;
                else
                    dp[i][j] = dp[i + 1][j];
            }
        }

        // 检查 s 是否为 t 的子序列
        int index = 0;
        for (char c : s) {
            index = dp[index][c - 'a'];
            if (index == n) return false;
            index++;
        }
        return true;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值