返回

深入分析:以最少字符改变满足三个条件的字符串

后端

导读

在 LeetCode 的众多算法题中,字符串处理问题一直备受关注。而动态规划法,作为解决这类问题的有力武器,往往能带来事半功倍的效果。今天,我们就一起来探索 LeetCode 上一道中等难度的字符串处理题目 —— 满足三条件之一需改变的最少字符数。

题目

给你两个字符串 st,若满足以下三个条件之一,则判定它们 相似

  1. s 可以通过删除一些字符(不改变顺序)得到 t
  2. t 可以通过删除一些字符(不改变顺序)得到 s
  3. st 一样。

例如,"abcd""ad" 是相似的,因为你可以通过删除 s 中的 bc 来得到 t

你的任务是找出使 st 相似所需的最小字符改变数。

示例

输入:s = "ab", t = "acb"
输出:1
解释:你可以通过删除 `t` 中的 `c` 来使 `s` 和 `t` 相似。
输入:s = "acb", t = "abc"
输出:2
解释:你可以通过删除 `s` 中的 `c` 和 `b` 来使 `s` 和 `t` 相似。

动态规划法

这道题目的本质是求解两个字符串之间的最长公共子序列(LCS)。而 LCS 的最优子结构可以通过动态规划法来高效地求解。

具体来说,我们定义 dp[i][j] 为字符串 s 的前 i 个字符和字符串 t 的前 j 个字符的最长公共子序列的长度。那么,我们可以通过以下递推公式来计算 dp[i][j]

  • 如果 s[i] == t[j],则 dp[i][j] = dp[i-1][j-1] + 1
  • 如果 s[i] != t[j],则 dp[i][j] = max(dp[i-1][j], dp[i][j-1])

一旦我们计算出了 dp 数组,那么使 st 相似所需的最小字符改变数就等于 s.length() + t.length() - 2 * dp[s.length()][t.length()]

代码实现

class Solution {
public:
    int minDistance(string s, string t) {
        int m = s.length();
        int n = t.length();
        int dp[m+1][n+1];
        
        for (int i = 0; i <= m; i++) {
            dp[i][0] = 0;
        }
        for (int j = 0; j <= n; j++) {
            dp[0][j] = 0;
        }
        
        for (int i = 1; i <= m; i++) {
            for (int j = 1; j <= n; j++) {
                if (s[i-1] == t[j-1]) {
                    dp[i][j] = dp[i-1][j-1] + 1;
                } else {
                    dp[i][j] = max(dp[i-1][j], dp[i][j-1]);
                }
            }
        }
        
        return s.length() + t.length() - 2 * dp[m][n];
    }
};

复杂度分析

  • 时间复杂度:O(mn),其中 mn 分别是字符串 st 的长度。
  • 空间复杂度:O(mn),用于存储 dp 数组。

结语

以上就是 LeetCode 上一道中等难度的字符串处理题目 —— 满足三条件之一需改变的最少字符数 的详细解析。通过使用动态规划法,我们可以高效地求解出使两个字符串相似的最小字符改变数。