最少前缀操作问题 | 豆包MarsCode AI刷题

69 阅读3分钟

问题描述

小U和小R有两个字符串,分别是SS和TT,现在小U需要通过对SS进行若干次操作,使其变成TT的一个前缀。操作可以是修改SS的某一个字符,或者删除SS末尾的字符。现在你需要帮助小U计算出,最少需要多少次操作才能让SS变成TT的前缀。


测试样例

样例1:

输入:S = "aba", T = "abb"
输出:1

样例2:

输入:S = "abcd", T = "efg"
输出:4

样例3:

输入:S = "xyz", T = "xy"
输出:1

样例4:

输入:S = "hello", T = "helloworld"
输出:0

样例5:

输入:S = "same", T = "same"
输出:0

上述为该题目的问题描述及样例,下面我来给出我的解题思路

题目分析

给定两个字符串 ST,要求对字符串 S 进行最少次数的操作,使得 S 成为 T 的前缀。允许的操作包括:

  1. 修改 S 的某个字符。
  2. 删除 S 的末尾字符。

解题思路

  1. 前缀匹配

    • 我们需要尽量保留 S 的前部分与 T 相同的部分,称之为公共前缀。
    • 如果某个位置的字符不相同,则需要一次修改操作。
  2. 字符串长度的关系

    • 如果 S 的长度比 T 长,则需要删除多余的字符。
    • 如果 S 的长度比 T 短,但公共前缀完全匹配,则不需要额外操作。
  3. 统计操作次数

    • 遍历两个字符串的字符比较:

      • 如果 S 的当前字符与 T 的对应字符不同,需要一次修改操作。
    • 统计公共前缀之后,处理 S 剩余部分:

      • 如果 S 的长度大于公共前缀,需要删除多余的字符。
  4. 特殊情况

    • 如果 ST 完全相等,则不需要任何操作。
    • 如果 S 的长度为 0,则需要在前缀处直接修改字符。

代码解释

以下代码实现了上述逻辑(java版):

public class Main {
    public static int solution(String S, String T) {
        int count = 0; // 操作计数器
        int lenS = S.length();
        int lenT = T.length();

        // 遍历 S 和 T 的每个字符
        for (int i = 0; i < lenS; i++) {
            if (i < lenT) {
                // 如果字符不同,累加修改操作
                if (S.charAt(i) != T.charAt(i)) {
                    count++;
                }
            } else {
                // 如果 S 的长度超出 T,需要删除剩余部分
                count += lenS - lenT;
                break;
            }
        }

        // 返回累积的操作次数
        return count;
    }

    public static void main(String[] args) {
        // 测试样例
        System.out.println(solution("aba", "abb") == 1); // 修改 1 次
        System.out.println(solution("abcd", "efg") == 4); // 修改 3 次 + 删除 1 次
        System.out.println(solution("xyz", "xy") == 1); // 删除 1 次
        System.out.println(solution("hello", "helloworld") == 0); // 不需要操作
        System.out.println(solution("same", "same") == 0); // 不需要操作
    }
}

测试用例分析

  1. 样例 1

    • 输入:S = "aba", T = "abb"
    • 公共前缀:ab
    • 修改 a -> b,需要 1 次操作。
    • 输出:1
  2. 样例 2

    • 输入:S = "abcd", T = "efg"
    • 公共前缀:无。
    • 修改 3 次:a -> e, b -> f, c -> g
    • 删除 1 次:d
    • 输出:4
  3. 样例 3

    • 输入:S = "xyz", T = "xy"
    • 公共前缀:xy
    • 删除 1 次:z
    • 输出:1
  4. 样例 4

    • 输入:S = "hello", T = "helloworld"
    • 公共前缀:hello
    • 无需修改或删除。
    • 输出:0
  5. 样例 5

    • 输入:S = "same", T = "same"
    • 公共前缀:same
    • 无需修改或删除。
    • 输出:0

复杂度分析

  1. 时间复杂度
    遍历字符串 S,复杂度为 O(lenS)O(\text{lenS})
  2. 空间复杂度
    只使用了常数空间变量,复杂度为 O(1)O(1)

总结

本题的核心在于找到 S 和 T 的最长公共前缀,然后根据两字符串的长度差和字符差异,计算最小的修改和删除次数。