题目链接: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
只含有小写字母以及字符'#'
题目分析
分析题目,首先想到了最简单的方法:使用栈(stack)。分别将两字符串进行入栈操作,每当遇到“#”则执行一次出栈。最后对比两栈内的字符,确定两字符串是否相同。注意判别栈空以及首字符为“#”的情况。此方法简单,但时间和空间复杂度较大。完整代码如下:
class Solution {
public:
bool backspaceCompare(string s, string t) {
stack<char> st_s;
st_s.push(s[0]);
if(s[0]=='#'){
st_s.pop();
}
stack<char> st_t;
st_t.push(t[0]);
if(t[0]=='#'){
st_t.pop();
}
for(int i=1;i<s.length();i++){
if(s[i]=='#'){
if(st_s.size()>0)st_s.pop();
}else{
st_s.push(s[i]);
}
}
for(int i=1;i<t.length();i++){
if(t[i]=='#'){
if(st_t.size()>0)st_t.pop();
}else{
st_t.push(t[i]);
}
}
if(st_s.size()!=st_t.size())return false;
while(st_s.size()>0){
if(st_s.top()!=st_t.top())return false;
st_s.pop();
st_t.pop();
}
return true;
}
};
继续进行优化:
使用双指针,可以获得常量级空间复杂度的解法。由于 # 号只会消除左边的一个字符,对于右边的字符无影响,所以我们选择从后往前遍历 s、t 字符串。在遍历过程中,如果遇到 # 号,则代表左边的一位字符将不会参与比较。
因此,设置两个变量skipS与skipT。以遍历字符串s为例,从左往右遍历过程中,若当前字符为 # ,则skipS++;若当前字符不为 # 且skipS不为0,则skipS--;只有当前字符不为 # 且skipS==0时,此字符才可参与比较。
若对比过程出现 s,t当前字符不匹配,则遍历结束,返回 false,若s,t都遍历结束,且都能一一匹配,则返回 true。完整代码如下:
class Solution {
public:
bool backspaceCompare(string S, string T) {
int i = S.length() - 1, j = T.length() - 1;
int skipS = 0, skipT = 0;
while (i >= 0 || j >= 0) {
//遍历s得到第一个可比较的字符
while (i >= 0) {
if (S[i] == '#') {
skipS++, i--;
} else if (skipS > 0) {
skipS--, i--;
} else {
break;
}
}
//遍历t得到第一个可比较的字符
while (j >= 0) {
if (T[j] == '#') {
skipT++, j--;
} else if (skipT > 0) {
skipT--, 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;
}
};