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

50 阅读5分钟

题目深度解析

题目理解

题目要求我们将字符串 S 通过最少的操作次数变成字符串 T 的前缀。操作可以是修改 S 中的某一个字符,或者删除 S 末尾的字符。我们需要计算出最少需要多少次操作才能让 S 变成 T 的前缀。

解题思路

  1. 理解前缀:前缀是指字符串的开头部分。例如,字符串 "hello" 的前缀可以是 "h""he""hel""hell""hello"

  2. 操作类型

    • 修改字符:将 S 中的某一个字符修改为 T 中对应位置的字符。
    • 删除字符:删除 S 末尾的字符,使其长度与 T 的前缀长度一致。
  3. 目标:通过最少的修改和删除操作,使 S 变成 T 的前缀。

数据结构选择

我们可以直接使用字符串的索引来遍历和比较字符。字符串在 Java 中是一个字符数组,可以通过索引访问每个字符。

算法步骤

  1. 初始化操作次数int operations = 0;
  2. 获取字符串长度int lenS = S.length(); 和 int lenT = T.length();
  3. 遍历字符串:使用 while 循环遍历字符串,直到较短的字符串结束。
  4. 比较字符:使用 if (S.charAt(i) == T.charAt(i)) 判断字符是否相同。
  5. 记录操作:如果字符不同,记录修改操作 operations++;
  6. 处理剩余字符:如果 S 的长度大于 T 的长度,记录删除操作 operations += lenS - lenT;

图解

假设我们有以下两个字符串:

  • S = "abcd"
  • T = "abef"

初始状态

plaintext

S: a b c d T: a b e f 第一次比较S[0] == T[0],字符相同,继续。

plaintext S: a b c d T: a b e f 第二次比较S[1] == T[1],字符相同,继续。

plaintext S: a b c d T: a b e f 第三次比较S[2] != T[2],字符不同,记录修改操作。

plaintext S: a b c d T: a b e f 第四次比较S[3] != T[3],字符不同,记录修改操作。

plaintext S: a b c d T: a b e f

  1. 处理剩余字符S 的长度等于 T 的长度,不需要删除操作。

最终操作次数为 2。

代码详解

public class Main { public static int solution(String S, String T) { // 初始化操作次数 int operations = 0;

    // 获取两个字符串的长度
    int lenS = S.length();
    int lenT = T.length();
    
    // 遍历字符串,直到较短的字符串结束
    int i = 0;
    while (i < lenS && i < lenT) {
        // 如果当前字符相同,继续比较下一个字符
        if (S.charAt(i) == T.charAt(i)) {
            i++;
        } else {
            // 如果当前字符不同,记录修改操作
            operations++;
            i++;
        }
    }
    
    // 如果S的长度大于T的长度,记录删除操作
    if (lenS > lenT) {
        operations += lenS - lenT;
    }
    
    return operations;
}

public static void main(String[] args) {
    System.out.println(solution("aba", "abb") == 1);
    System.out.println(solution("abcd", "efg") == 4);
    System.out.println(solution("xyz", "xy") == 1);
    System.out.println(solution("hello", "helloworld") == 0);
    System.out.println(solution("same", "same") == 0);
}

}

代码解释

  1. 初始化操作次数int operations = 0;

    • 用于记录操作次数。
  2. 获取字符串长度int lenS = S.length(); 和 int lenT = T.length();

    • 获取字符串 S 和 T 的长度,用于遍历和比较。
  3. 遍历字符串while (i < lenS && i < lenT)

    • 使用 while 循环遍历字符串,直到较短的字符串结束。
  4. 比较字符if (S.charAt(i) == T.charAt(i))

    • 判断当前字符是否相同,如果相同则继续比较下一个字符。
  5. 记录操作operations++;

    • 如果字符不同,记录修改操作。
  6. 处理剩余字符if (lenS > lenT) { operations += lenS - lenT; }

    • 如果 S 的长度大于 T 的长度,记录删除操作。

知识点总结

  1. 字符串操作

    • 字符串长度String.length() 方法用于获取字符串的长度。
    • 字符访问String.charAt(int index) 方法用于访问字符串中的某个字符。
  2. 循环控制

    • while 循环:用于遍历字符串,直到较短的字符串结束。
  3. 条件判断

    • if 语句:用于判断字符是否相同,并记录操作次数。
  4. 操作记录

    • 操作次数:使用一个变量记录操作次数,包括修改和删除操作。

分析与理解

  1. 时间复杂度

    • 该算法的时间复杂度为 O(n),其中 n 是较短字符串的长度。因为我们只需要遍历一次字符串,并进行常数时间的比较和操作。
  2. 空间复杂度

    • 该算法的空间复杂度为 O(1),因为我们只使用了常数个额外的变量来存储操作次数和索引。
  3. 边界情况

    • 如果 S 和 T 完全相同,操作次数为 0。
    • 如果 S 的长度大于 T 的长度,需要删除多余的字符。
    • 如果 S 的长度小于 T 的长度,只需要修改字符。

学习建议

  1. 基础知识

    • 掌握字符串的基本操作,如获取长度、访问字符等。
    • 熟悉循环和条件判断的使用,理解如何通过循环遍历字符串。
  2. 算法思维

    • 学会分析问题的本质,理解题目要求的最少操作次数。
    • 通过图解和实例分析,加深对算法的理解。
  3. 代码实现

    • 多练习编写代码,熟悉 Java 的字符串操作和控制结构。
    • 尝试不同的测试用例,验证代码的正确性和鲁棒性。
  4. 进阶学习

    • 学习动态规划等高级算法,解决更复杂的问题。
    • 阅读相关书籍和文章,提升算法和数据结构的理解。

总结

通过深度解析题目,我们理解了如何通过最少的操作次数将字符串 S 变成字符串 T 的前缀。我们选择了合适的数据结构和算法,并通过代码实现了这一目标。通过分析和理解,我们总结了相关的知识点,并给出了学习建议。