返回

深入剖析:LeetCode 72 号问题——判断子序列的奥秘

Android

子序列:揭秘字符串中的隐藏序列

什么是子序列?

想象一下你有一串珠子,你可以随意取走一些珠子,而不用改变其余珠子的顺序。这就是子序列的概念。它是一个序列,由原始序列中连续(或不连续)的元素组成。例如,单词 "ace" 就是 "abcdef" 的一个子序列,因为 "ace" 中的字符与 "abcdef" 中的字符顺序一致。

判断子序列:LeetCode 72 号问题

LeetCode 上有一道经典问题(72 号):判断一个字符串 s 是否是另一个字符串 t 的子序列。换句话说,我们想知道 s 中的字符是否可以在 t 中按顺序找到,而不改变 t 中字符的相对顺序。

动态规划解法

解决此问题最流行的方法是动态规划。它是一种分而治之的算法,将问题分解成更小的子问题,然后逐个解决。对于子序列问题,我们可以使用一个二维数组 dp 来记录子序列信息。dp[i][j] 表示 s 的前 i 个字符是否是 t 的前 j 个字符的子序列。

算法步骤如下:

  1. 初始化 dp[0][0]true,表示空字符串是空字符串的子序列。
  2. 遍历 s 的每个字符 i
    • 遍历 t 的每个字符 j
      • 如果 s[i] 等于 t[j],则 dp[i][j]dp[i-1][j-1](即前面的子序列加上这个字符)。
      • 否则,dp[i][j]dp[i-1][j](即忽略当前字符)。
  3. 返回 dp[s.length][t.length]

字符串匹配解法

另一种解决此问题的方法是字符串匹配。我们可以使用滑窗算法来查找 s 中每个字符在 t 中的第一个匹配项。如果找到所有字符的匹配项,则 st 的子序列。

算法步骤如下:

  1. 初始化两个指针 ij,分别指向 st 的第一个字符。
  2. 循环,直到 ij 超过各自字符串的长度:
    • 如果 s[i] 等于 t[j],则 ij 均加 1。
    • 否则,j 加 1。
  3. 如果 i 等于 s 的长度,则 st 的子序列。

代码示例

动态规划解法:

public boolean isSubsequence(String s, String t) {
    int m = s.length(), n = t.length();
    boolean[][] dp = new boolean[m + 1][n + 1];

    dp[0][0] = true;
    for (int i = 1; i <= m; i++) {
        for (int j = 1; j <= n; j++) {
            if (s.charAt(i - 1) == t.charAt(j - 1)) {
                dp[i][j] = dp[i - 1][j - 1];
            } else {
                dp[i][j] = dp[i - 1][j];
            }
        }
    }
    return dp[m][n];
}

字符串匹配解法:

public boolean isSubsequence(String s, String t) {
    int i = 0, j = 0;
    while (i < s.length() && j < t.length()) {
        if (s.charAt(i) == t.charAt(j)) {
            i++;
        }
        j++;
    }
    return i == s.length();
}

总结

子序列问题是一个重要的算法问题,考验我们的算法设计和分析能力。通过动态规划和字符串匹配两种解法,我们可以高效地解决这一难题。这篇文章不仅提供了详细的解题步骤,还配有清晰的代码示例,帮助你深入理解子序列概念和算法技巧。希望通过本文,你对算法和字符串处理有了进一步的认识。

常见问题解答

1. 什么是动态规划算法?

动态规划是一种分而治之的算法,将问题分解成更小的子问题,然后逐个解决。

2. 如何用字符串匹配解决子序列问题?

可以使用滑窗算法来查找 s 中每个字符在 t 中的第一个匹配项。如果找到所有字符的匹配项,则 st 的子序列。

3. 动态规划解法和字符串匹配解法哪个更好?

动态规划解法时间复杂度为 O(mn),其中 mn 分别是 st 的长度。字符串匹配解法时间复杂度为 O(n)。当 m 远小于 n 时,字符串匹配解法更优。

4. 子序列在实际应用中的场景有哪些?

子序列广泛用于比较和分析字符串,例如查找相似单词、检查输入有效性以及解决基因测序等生物信息学问题。

5. 如何在代码中实现子序列判断算法?

本文提供了两种算法的详细 Java 代码示例。你可以将其复制到你的开发环境中,并用自己的输入数据进行测试。