1. 题目来源
2. 题目说明
3. 题目解析
方法一:栈
采用栈的思想,后进先出,遇到 #
字符,若前面有字符存在就将它弹出,遍历一遍字符串即可还原这个退格后的字符串。最后比较两字符串是否相等即可。
不是真的需要用栈,std::string
有 push_back()、pop_back()
操作,也可以利用栈的思想完成该操作。
时间复杂度:
O
(
N
+
M
)
O(N+M)
O(N+M)
空间复杂度:
O
(
N
+
M
)
O(N+M)
O(N+M)
参见代码如下:
class Solution {
public:
bool backspaceCompare(string S, string T) {
return check(S) == check(T);
}
string check(string s) {
string res;
for (int i = 0; i < s.size(); ++i) {
if (s[i] != '#') res += s[i];
else if (!res.empty()) res.pop_back();
}
return res;
}
};
方法二:双指针
参考了官方题解,时间复杂度不变的情况下,采用双指针算法将空间优化到了 O ( 1 ) O(1) O(1)
一个字符是否被删除,仅取决于原字符串中该字符后面的退格符,而与前面的退格符无关。那么可以逆序的遍历字符串,就能够确定当前字符是否会被删除。
具体流程为:
- 定义
s
为当前待删除的字符的数量,逆序遍历字符串 - 当前字符为
#
,则s++
- 若当前为普通字符,分为两种情况考虑
- 若
s
为 0,则当前字符不能被删除 - 若
s
不为 0,则当前字符删除,s--
- 若
基于该思想,可以定义两个指针,分别指向两字符串的末尾。逆序遍历两字符串,直到两个指针都能各自确定一个字符,然后将两个字符进行比较是否相等。遍历完字符串为止。
注意这两个指针停住的位置,一定是一个不被退格的有效字符位置,两个指针遍历完毕后会指向 -1 位置。
class Solution {
public:
bool backspaceCompare(string S, string T) {
int i = S.size() - 1, j = T.size() - 1;
int s = 0, t = 0;
while (i >= 0 || j >= 0) {
while (i >= 0) {
if (S[i] == '#') s++, i--;
else if (s > 0) s--, i--;
else break;
}
while (j >= 0) {
if (T[j] == '#') t++, j--;
else if (t > 0) t--, j--;
else break;
}
if (i >= 0 && j >= 0) {
if (S[i] != T[j]) return false;
} else {
if (i >= 0 || j >= 0) return false;
}
--i, --j;
}
return true;
}
};