题目来源:力扣(LeetCode)https://leetcode-cn.com/problems/backspace-string-compare/
给定 S
和 T
两个字符串,当它们分别被输入到空白的文本编辑器后,判断二者是否相等,并返回结果。 #
代表退格字符。
**注意:**如果对空文本输入退格字符,文本继续为空。
示例 1:
输入:S = "ab#c", T = "ad#c"
输出:true
解释:S 和 T 都会变成 “ac”。
示例 2:
输入:S = "ab##", T = "c#d#"
输出:true
解释:S 和 T 都会变成 “”。
示例 3:
输入:S = "a##c", T = "#a#c"
输出:true
解释:S 和 T 都会变成 “c”。
示例 4:
输入:S = "a#c", T = "b"
输出:false
解释:S 会变成 “c”,但 T 仍然是 “b”。
提示:
1 <= S.length <= 200
1 <= T.length <= 200
S
和 T
只含有小写字母以及字符 '#'
。进阶:
O(N)
的时间复杂度和 O(1)
的空间复杂度解决该问题吗?先看题目,题目给定两个字符串 S
和 T
,其中两个字符串中可能含有 #
字符,这里 #
字符,表示退格字符。
题目要求,若将 S
和 T
分别输入文本编辑器,判断是否相等?
其中还有提示及需要注意的部分:
S
和 T
只含有小写字母以及字符 '#'
。S
和 T
两者的长度都大于或等于 1,小于或等于 200。这里看看题目示例 1 和示例 2:
示例 1
输入:S = "ab#c", T = "ad#c"
S
字符串中,字符 b 后面紧跟 #
字符,那么 b 字符将会被删除,所以这里最终输出的结果会是 ac;
T
字符串中,字符 d 后面跟 #
字符,那么 d 字符将会被删除,所以输出的结果也是 ac。
所以两者相同。
示例 2
输入:S = "ab##", T = "c#d#"
这里跟示例 1 不同的地方在于,这里存在两个 “#” 字符。这里也看看是如何变化的?
S
字符串中,字符 b 后面紧跟两个 #
字符。首先先明确在文本输入字符串时,是按照顺序输入的,那么字符 b 遇到第一个 #
时,先将字符 b 删除,剩下字符 a,再次遇到第二个 #
时,a 字符被删除,那么最终文本为空;
T
字符串中,这里比较好理解,就是输入 c 字符,然后被删除,接着输入字符 d,再次删除,最终文本也为空。
所以这两者都相同。
结合这两个示例看,不管 #
字符有多少,只要遇到 #
字符,(除空文本外)总有对应的字符需要被删除。那么我们可以使用栈来模拟这个过程,遍历字符串,判断其中的字符:
#
符号,那么将字符压入栈中;#
符号,那么将栈顶的字符弹出。这里需要注意,本篇文章用 list 实现栈,这里 list 为空时需要注意弹出元素会抛出异常。
具体代码实现如下:
class Solution:
def backspaceCompare(self, S: str, T: str) -> bool:
def text_input(text):
# 栈
stack = []
# 遍历字符串
for ch in text:
# 普通字符入栈
if ch != "#":
stack.append(ch)
# "#" 字符且栈非空时,弹出
elif stack:
stack.pop()
return ''.join(stack)
# 判断两者是否相同
return text_input(S) == text_input(T)
S
和 T
两个字符串的长度。这里需要分别遍历两个字符串一次。根据前面对示例的分析,我们可以发现,#
字符只会影响其前面的普通字符,也就是说对于普通字符是否会被删除,取决于它后面的 #
字符。那么,我们可以考虑逆序遍历字符串,判断是否存在 #
字符,进而确定是否需要删除字符。
再看示例 2,
输入:S = "ab##", T = "c#d#"
这里 S
有两个连续 #
,这里逆序遍历时,不能单纯的仅对前一位字符进行判断。在这里说下具体的做法:
#
出现的次数;#
时,那么 cnt 要相应加 1;#
字符,此处不需要变动;在将前面的做法实现时,遍历字符串,根据 #
的数量 cnt 对字符串进行处理,会遇到这样的情况:
具体的代码实现如下。
class Solution:
def backspaceCompare(self, S: str, T: str) -> bool:
# 定义指针,p 指向 S 末尾,q 指向 T 末尾
p = len(S) - 1
q = len(T) - 1
# 定义变量 cnt_S,cnt_T,分别 '#' 的数量变化
cnt_S = 0
cnt_T = 0
while p >= 0 or q >= 0:
# 先遍历字符串 S
while p >= 0:
# 字符为 '#',cnt_S 加 1,同时 p 指针往左移动
if S[p] == '#':
cnt_S += 1
p -= 1
# 字符不为 '#',且 cnt_S 不为 0,当前字符要删除,更新 cnt_S,移动 p 指针
elif cnt_S > 0:
cnt_S -= 1
p -= 1
# 为普通字符,且 cnt_S 为 0,跳出循环,等待判断
else:
break
# 遍历字符串 T
# 逻辑与上面相同
while q >= 0:
if T[q] == '#':
cnt_T += 1
q -= 1
elif cnt_T > 0:
cnt_T -= 1
q -= 1
else:
break
# 此时判断两指针对应的字符
# 字符串都未遍历完的情况
if p >= 0 and q >= 0:
# 对应字符不同,直接返回 False
if S[p] != T[q]:
return False
# 字符串只有一个遍历完的情况
elif p >= 0 or q >= 0:
return False
# 上面情况不满足时,需要继续判断,继续移动 p, q 指针
p -= 1
q -= 1
return True
S
和 T
两个字符串的长度。这里需要分别遍历两个字符串一次。公众号 【书所集录】