LeetCode 面试题 01.05. 一次编辑
题目描述

题意分析
判断两个由英文字符组成的字符串,能否通过至多一次插入、删除或替换变得相等。允许零次编辑,因此原本相同的字符串也应返回
true。
解法:双指针比较
核心思路
[!blue]
一次插入或删除只改变一个字符的长度,替换不改变长度。因此长度差大于一时一定无解;其余情况将较短串统一放在
first,较长串放在second,只需考虑等长与相差一两种情况。用
i、j分别指向两串还未处理的字符,edits记录已用的编辑次数。当前字符相同,就保留这一对并让两个指针同时前进。第一次失配时,长度关系已经决定了唯一可能的操作类型,无需像一般编辑距离那样枚举三种分支。若两串等长,一次插入或删除都会让长度不再相等,只能替换当前字符。因此同时跳过两边的失配字符,相当于把它们改成相同字符,再比较后缀。
若长度相差一,唯一一次编辑必须用于删除长串中的一个字符,或等价地向短串插入它。已有前缀都相同,若要修复当前失配,就应跳过
second[j],只让j前进,保留first[i]等待与长串的下一个字符比较。两种情况都会消耗一次编辑,此后再遇失配就直接失败。循环结束后无需额外统计尾部:等长时两个指针始终同步,必然同时结束;长串多一位时,如果中途已经跳过一个字符,此后始终有
j = i + 1,也会同时结束。如果中途一直匹配,则长串恰好剩最后一个字符,而编辑次数仍为零,正好可用一次插入或删除处理。因此到达循环末尾就能返回true,空串情形也由长度检查和这个结论自然覆盖。
解题步骤
- 长度差超过一就返回
false;若first更长,交换参数后再处理。- 从
i = 0、j = 0开始比较。相同则两个指针一起前进。- 不同则增加
edits;若超过一,立即返回false。- 等长时两侧都跳过当前字符;不等长时只跳过长串当前字符。
- 没有第二次失配而结束比较,就返回
true。
代码实现
class Solution {
public boolean oneEditAway(String first, String second) {
if (Math.abs(first.length() - second.length()) > 1) {
return false;
}
if (first.length() > second.length()) {
return oneEditAway(second, first);
}
int i = 0;
int j = 0;
int edits = 0;
while (i < first.length() && j < second.length()) {
if (first.charAt(i) == second.charAt(j)) {
i++;
j++;
} else {
edits++;
if (edits > 1) {
return false;
}
// 等长失配同时跳过表示替换,不等长只跳过长串
if (first.length() == second.length()) {
i++;
}
j++;
}
}
// 末尾若仍有一项,长度关系保证可由尚未使用的一次编辑处理
return true;
}
}
func oneEditAway(first string, second string) bool {
if absInt(len(first)-len(second)) > 1 {
return false
}
if len(first) > len(second) {
return oneEditAway(second, first)
}
i, j := 0, 0
edits := 0
for i < len(first) && j < len(second) {
if first[i] == second[j] {
i++
j++
} else {
edits++
if edits > 1 {
return false
}
// 等长失配同时跳过表示替换,不等长只跳过长串
if len(first) == len(second) {
i++
}
j++
}
}
// 末尾若仍有一项,长度关系保证可由尚未使用的一次编辑处理
return true
}
func absInt(x int) int {
if x < 0 {
return -x
}
return x
}
复杂度分析
- 时间复杂度:$O(\min(m,n)+1)$,其中
m、n是两串长度。每次匹配都推进短串指针,失配至多多跳过一个长串字符;交换参数最多发生一次。- 空间复杂度:$O(1)$。只有两个下标和编辑计数,参数交换也只增加常数层调用。
关键点总结
[!green]
- 长度相等时只可能替换,长度相差一时只可能插入或删除。
- 第一次失配按长度关系恢复后缀对齐,之后必须完全匹配。
- 末尾是否还剩字符,与此前是否已用编辑由指针位置自动对应。
易错点总结
[!yellow]
- 省略长度差检查,会把过长的剩余后缀误认为一次编辑就能处理。
- 长度不等时同时移动两个指针,会跳过短串中本来还要比较的字符。
- 长度相等时只移动一侧,会把替换错误地当成插入或删除。
- 题目要求“至多一次”,不能拒绝完全相同的字符串或两个空串。
相似题目
| 题目 | 难度 | 关联与区别 |
|---|---|---|
| 161. 相隔为 1 的编辑距离 | 中等 | 原题要求恰好一次编辑,本题允许至多一次,因此两个本就相同的字符串应返回true。 |
| 72. 编辑距离 | 中等 | 原题计算任意编辑距离,本题上限只有1,可由长度关系直接决定首次失配时的指针移动。 |
转载与许可
许可
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处!