大家好,我是 @负雪明烛。👈👈 点击关注,优质题解不间断。

题目大意

一次编辑操作可以是:增加、删除、替换一个字符。
判断两个字符串能否可以通过一次或零次编辑操作互相得到。

今天的题目很好懂,直接开干。

解题方法

情况分析

我拿到这个题目的第一想法是按「统计词频」的方法做,但即使「词频」相差小于等于 1,还有排列顺序的问题,因此必须放弃这个做法。

首先我们可以把字符串长度相差大于 面试题 01.05. 一次编辑 - 图1 的,都排除掉。比如示例 2 "pales""pal"

现在 面试题 01.05. 一次编辑 - 图2面试题 01.05. 一次编辑 - 图3长度相等或者长度相差 面试题 01.05. 一次编辑 - 图4.

如果 面试题 01.05. 一次编辑 - 图5能通过一次或者零次编辑得到 面试题 01.05. 一次编辑 - 图6,则可能有下面 3 种情况:

  1. 假如面试题 01.05. 一次编辑 - 图7面试题 01.05. 一次编辑 - 图8长度相等:
    1. 两者可能完全相等,即通过零次编辑得到。
    2. 两者中只有一个字符不等,即通过一次替换操作得到。(如 first = "abc"second = "abe"
  2. 假如面试题 01.05. 一次编辑 - 图9的长度比 面试题 01.05. 一次编辑 - 图10长度大面试题 01.05. 一次编辑 - 图11
    1. 只能是删除 面试题 01.05. 一次编辑 - 图12中的一个字符得到 面试题 01.05. 一次编辑 - 图13;(如 first = "abc"second = "ac"
  3. 假如面试题 01.05. 一次编辑 - 图14的长度比 面试题 01.05. 一次编辑 - 图15长度大面试题 01.05. 一次编辑 - 图16
    1. 交换两者,即变成了情况 2.(如 first = "ac"second = "abc"

问题拆解以后,思路是不是清晰很多了?

解法:双指针

如果两者的字符长度差距大于 $1$,直接不符合题意。

那么,现在两个字符串就最多只有一个字符不同,我们使用双指针面试题 01.05. 一次编辑 - 图17面试题 01.05. 一次编辑 - 图18之间的 面试题 01.05. 一次编辑 - 图19即可。

用两个指针分别指向 面试题 01.05. 一次编辑 - 图20面试题 01.05. 一次编辑 - 图21的两个字符,根据字符的是否相等,判断移动哪个指针。

我们只考虑 面试题 01.05. 一次编辑 - 图22长度与 面试题 01.05. 一次编辑 - 图23相等或者 面试题 01.05. 一次编辑 - 图24长度比面试题 01.05. 一次编辑 - 图25面试题 01.05. 一次编辑 - 图26的情况,下面画图分析:

  1. 面试题 01.05. 一次编辑 - 图27长度与 面试题 01.05. 一次编辑 - 图28相等

两个指针一起从左向右移动,每次各移动一步,当遇到不等的字符时仍然继续都右移。

统计不同的字符个数 面试题 01.05. 一次编辑 - 图29

符合要求的 面试题 01.05. 一次编辑 - 图30

  1. 面试题 01.05. 一次编辑 - 图31长度比 面试题 01.05. 一次编辑 - 图32大 1

两个指针一起从左向右移动,每次各移动一步,当遇到不等的字符时 面试题 01.05. 一次编辑 - 图33右移,面试题 01.05. 一次编辑 - 图34原地等待一次。

统计不同的字符个数 面试题 01.05. 一次编辑 - 图35

符合要求的 面试题 01.05. 一次编辑 - 图36

  1. 面试题 01.05. 一次编辑 - 图37长度比 面试题 01.05. 一次编辑 - 图38大 1

交换两者,转换成情况 2 处理。

代码

上面的思路理解以后,代码还是很好写出的。

  1. 先判断长度相差 $> 1$,直接返回 $False$
  2. 如果 面试题 01.05. 一次编辑 - 图39长度等于 面试题 01.05. 一次编辑 - 图40长度 $+ 1$,则交换两者,仍然调用该函数。
  3. 使用双指针面试题 01.05. 一次编辑 - 图41分别指向 面试题 01.05. 一次编辑 - 图42面试题 01.05. 一次编辑 - 图43,每次都向右移动一步
    1. 当两者指向的字符不同时,diff ++,如果面试题 01.05. 一次编辑 - 图44面试题 01.05. 一次编辑 - 图45长度大 $1$,则让 面试题 01.05. 一次编辑 - 图46原地等待。
    2. 面试题 01.05. 一次编辑 - 图47时,返回 面试题 01.05. 一次编辑 - 图48
  4. 当比较完成之后,仍然没有发现 面试题 01.05. 一次编辑 - 图49,说明可以通过一次编辑得到,返回 $True$

代码如下:

  1. class Solution(object):
  2. def oneEditAway(self, first, second):
  3. M, N = len(first), len(second)
  4. if abs(M - N) > 1:
  5. return False
  6. if N == M + 1:
  7. return self.oneEditAway(second, first)
  8. i, j = 0, 0
  9. diff = 0
  10. while i < M and j < N:
  11. if first[i] != second[j]:
  12. diff += 1
  13. if diff >= 2:
  14. return False
  15. if M > N:
  16. j -= 1 # 为了让原地等待,先回退一步,后面会再向右移动一步
  17. i += 1 # 每次都向右移动一步
  18. j += 1 # 每次都向右移动一步
  19. return True

复杂度

  • 时间复杂度:$O(N)$,面试题 01.05. 一次编辑 - 图50是字符串长度。
  • 空间复杂度:$O(1)$,没用额外空间。

    总结

  1. 今天这个题主要是分情况讨论,想明白各种情况,思路清晰了的话,代码不难。

我是 @负雪明烛 ,刷算法题 1000 多道,写了 1000 多篇算法题解,收获阅读量 300 万。
关注我,你将不会错过我的精彩动画题解、面试题分享、组队刷题活动,进入主页 @负雪明烛 右侧有刷题组织,从此刷题不再孤单。