题目
给定 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”
思路
方法一:重构字符串(栈的思想)
- 如果遇到退格符,则弹出栈顶元素
- 如果是普通字符,则入栈
java代码如下:
class Solution {
public boolean backspaceCompare(String s, String t){
StringBuilder sb1 = new StringBuilder();//模拟栈
StringBuilder sb2 = new StringBuilder();//模拟栈
//分别处理两个String
for(char c : s.toCharArray()){//将字符串s转化成字符数组,并遍历每一个字符
if(c != '#'){
sb1.append(c);//模拟入栈
} else if (sb1.length() > 0){//如果是退格符,则弹出栈顶元素,同时并且要非空
sb1.deleteCharAt(sb1.length() - 1);//模拟弹栈,栈顶元素相当于字符串的最后一个字符
}
}
for(char c : t.toCharArray()){
if(c != '#'){
sb2.append(c);
} else if (sb2.length() > 0){
sb2.deleteCharAt(sb2.length() - 1);
}
}
return sb1.toString().equals(sb2.toString());//将StringBuilder转化成String类型
}
}
- 空间复杂度O(n)
方法二:双指针法
一个字符是否会被删掉,只取决于该字符后面的退格符,而与该字符前面的退格符无关
因此可以逆序地遍历字符串,就可以立即确定当前字符是否会被删掉
这里定义skip
表示当前要删除的字符的数量,每遍历到一个字符
- 如果字符是退格符,则
skip++
,表示要删除一个字符 - 如果字符是普通字符:
(1)若skip == 0
,则当前字符不需要删除
(2)若skip!= 0
,则当前字符要删除,skip--
然后定义两个指针,分别指向两字符串的末尾;每次让两指针逆序地遍历两字符串,直到两字符串能够各自确定一个字符,然后将这两个字符进行比较;重复这一过程直到找到的两个字符不相等,或遍历完字符串为止。
java代码如下:
class Solution {
public boolean backspaceCompare(String s, String t){
int i = s.length() - 1;
int j = t.length() - 1 ;
int skipS = 0, skipT = 0;//记录S和T的#数量
while(i >= 0 || j >= 0){
while(i >= 0){
if(s.charAt(i) == '#'){//如果是退格符
skipS++;
i--;
} else if (skipS > 0){//如果是普通字符,并且需要删除
skipS--;
i--;
} else {
break;//以上条件均不满足的话,表示找一个不需要删除的字符,即一个可供比较的字符
}
}
while(j >= 0){
if(t.charAt(j) == '#'){
skipT++;
j--;
} else if (skipT > 0){
skipT--;
j--;
} else{
break;
}
}
//都找到了可比较的字符之后,开始比较
if(i >= 0 && j >= 0){//如果二者都没遍历完
if(s.charAt(i) != t.charAt(j)){//并且字符不相等的话
return false;
}
} else if(i >= 0 || j >= 0){//如果二者有一个遍历完了
return false;
}
i--;
j--;
}
return true;
}
}
- 空间复杂度O(1)