题目链接:844. 比较含退格的字符串
题目:
给定 s 和 t 两个字符串,当它们分别被输入到空白的文本编辑器后,如果两者相等,返回 true 。# 代表退格字符。
注意:如果对空文本输入退格字符,文本继续为空。
示例 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 = “b”
输出:false
解释:s 会变成 “c”,但 t 仍然是 “b”。
提示:
1 <= s.length, t.length <= 200
s 和 t 只含有小写字母以及字符 ‘#’
进阶: 你可以用 O(n) 的时间复杂度和 O(1) 的空间复杂度解决该问题吗?
思路和算法:
这题我采用的是双指针的方法,时间复杂度为O(N+M),其中N+M是字符串s和字符串t的长度,空间复杂度为O(1)。
代码(c++):
class Solution {
public:
bool backspaceCompare(string s, string t) {
int p1 = s.length() - 1; //遍历字符串s
int p2 = t.length() - 1; //遍历字符串t
int cnt1 = 0; //用来记录字符串s的#个数
int cnt2 = 0; //用来记录字符串t的#个数
while (p1 >= 0 || p2 >= 0) {
while (p1 >= 0) { //字符串s中遇到#则退格去除
if (s[p1] == '#') {
++cnt1;
--p1;
}
else if (cnt1 > 0) {
--cnt1;
--p1;
}
else {
break;
}
}
while (p2 >= 0) { //字符串t中遇到#则退格去除
if (t[p2] == '#') {
++cnt2;
--p2;
}
else if (cnt2 > 0) {
--cnt2;
--p2;
}
else {
break;
}
}
if (p1 >= 0 && p2 >= 0) {
if (s[p1] != t[p2]) return false;
}
else {
if(p1 >= 0 || p2 >= 0) return false; //这里是为了排除退格操作后,p1和p2小于零的情况,例如示例2中的情况,去除#号后,p1和p2都小于零,但是两个字符串实际上都是空字符串,应该返回true,而不应该在这返回false
}
--p1;
--p2;
}
return true;
}
};
在我看来,我觉得用双指针还蛮麻烦的,因为绕来绕去的逻辑对我而言,我有点迷,这题逻辑我能理清个大概,对于有些不通过的示例也还是需要多调试几遍才能通过,感觉如果要是面试到这题,现场可能会由于紧张而调试不出来,但也能写个大概,对自己的实力还是拿捏的准准的。下面的重构法是我从官方题解那儿“偷”学过来的,感觉这种办法不绕,更适合我,只不过在空间复杂度上会吃点亏,空间复杂度变为了O(N+M)。
class Solution {
public:
/** 重构法 */
string func(string str) {
string res;
for (auto ch : str) {
if (ch != '#') {
res.push_back(ch);
}
else if (!res.empty()) {
res.pop_back();
}
}
return res;
}
bool backspaceCompare(string s, string t) {
return func(s) == func(t);
}
};
在重构这种方法中,有点类似于压栈出栈的这种味道。