一,题目详情
1,问题描述
小U和小R有两个字符串,分别是 S 和 T,现在小U需要通过对 S 进行若干次操作,使其变成 T 的一个前缀。操作可以是修改 S 的某一个字符,或者删除 S 末尾的字符。现在需要帮助小U计算出,最少需要多少次操作才能让 S 变成 T 的前缀。
2,测试样例
样例1:
输入:S = "aba", T = "abb"
输出:1
解释:将S的第三个字符从a改为b,操作次数为1。
样例2:
输入:S = "abcd", T = "efg"
输出:4
解释:需要删除S的最后一个字符,再将前三个字符全部修改,或者直接全部删除,操作次数为4。
样例3:
输入:S = "xyz", T = "xy"
输出:1
解释:删除S的最后一个字符z,操作次数为1。
样例4:
输入:S = "hello", T = "helloworld"
输出:0
解释:S已经是T的前缀,无需操作。
样例5:
输入:S = "same", T = "same"
输出:0
解释:S和T相同,无需操作。
二,解题思路
1,问题分析
我们需要找到最少的操作次数,使得S通过修改字符和删除末尾字符的操作变成T的前缀。操作包括修改和删除,其中删除只能是删除末尾的字符。
2,算法策略
我们可以考虑所有可能的公共前缀长度k(从0到min(len(S), len(T))),对于每个k,计算需要的删除操作次数(S的长度减去k)和修改操作次数(前k个字符中不同的字符数)。然后找到所有k中总操作次数最小的那个。
具体步骤如下:
- 初始化最小操作次数为一个很大的数。
- 遍历所有可能的公共前缀长度k(从0到min(len(S), len(T)))。
- 对于每个k,计算需要的删除操作次数(S的长度减去k)和修改操作次数(前k个字符中不同的字符数)。
- 更新最小操作次数。
- 最后返回最小操作次数。
3,逐步推演(以样例1为例)
输入:S = "aba", T = "abb"
k | delete_ops | modify_ops | total_ops |
---|---|---|---|
0 | 3 | 0 | 3 |
1 | 2 | 0(S[0]=T[0]) | 2 |
2 | 1 | 1(S[1]≠T[1]) | 2 |
3 | 0 | 1(S[2]≠T[2]) | 1 |
所以最小操作次数为1。
三,代码实现
Python复制
ini
def solution(S: str, T: str) -> int:
n = len(S)
m = len(T)
max_k = min(n, m)
min_ops = float('inf')
for k in range(0, max_k + 1):
delete_ops = n - k
modify_ops = 0
for i in range(k):
if S[i] != T[i]:
modify_ops += 1
total_ops = delete_ops + modify_ops
if total_ops < min_ops:
min_ops = total_ops
return min_ops
1,复杂度分析
-
时间复杂度:O(n*m)
- 外层循环运行min(n, m)+1次,内层循环运行k次,总次数为O(n*m)
-
空间复杂度:O(1)
- 仅使用常数级额外空间
2,边界测试
Python复制
css
if __name__ == '__main__':
# 常规测试
print(solution("aba", "abb") == 1)
print(solution("abcd", "efg") == 4)
print(solution("xyz", "xy") == 1)
print(solution("hello", "helloworld") == 0)
print(solution("same", "same") == 0)
# 边界测试:S为空
print(solution("", "abc") == 0)
# 边界测试:T为空
print(solution("abc", "") == 3)
# 边界测试:S和T长度相同但不同
print(solution("abc", "abd") == 1)
四,总结
通过遍历所有可能的公共前缀长度并计算对应的操作次数,我们实现了:
- 找到最少操作次数:通过比较所有可能的k,找到最优解
- 清晰的逻辑:分步计算删除和修改操作次数
- 普适性:适用于所有字符串S和T
这种解法不仅高效,还易于理解和实现。当遇到"需要通过操作使一个字符串成为另一个字符串的前缀"类问题时,遍历所有可能的公共前缀长度并计算对应操作次数往往是解决问题的关键策略。