一、题目内容
二、题目分析
这道题目除了双指针其实还可以用栈写。首先定义两个空栈,然后分别进行如下操作:
从头开始,如果当前字符是#,就对栈进行出栈操作,当然出栈前要先判断栈是否为空。如果当前字符不为#,就将其放入栈中,最后得到两个装满比较后字符的栈,然后比较两个栈中内容是否相同,相同则返回true,否则返回false。
如果使用这种写法的话,使用C++会比较方便,因为c++封装好了一个stack,而java中虽然Stack是vector的子类,但是都知道java是基于C++形成的,所以自然没有C++快。
代码:
public boolean backspaceCompare(String s, String t) {
Stack<Character> s1=new Stack<>();
Stack<Character> s2=new Stack<>();
int p1=0,p2=0;
while(p1<s.length()){
if(s.charAt(p1)=='#'){
if(!s1.empty()){
s1.pop();
}
}
else{
s1.push(s.charAt(p1));
}
p1++;
}
while(p2<t.length()){
if(t.charAt(p2)=='#'){
if(!s2.empty()){
s2.pop();
}
}
else{
s2.push(t.charAt(p2));
}
p2++;
}
if(s1.empty()&&s2.empty())
return true;
if((!s1.empty()&&s2.empty())||(s1.empty()&&!s2.empty())||s1.size()!=s2.size())
return false;
while(!s1.empty()&&!s2.empty()){
if(s1.pop()!=s2.pop())
return false;
}
return true;
}
因为在java中用stack,确实算不上快,所以提交的结果也不如人意,好在还可以使用双指针法。
首先请思考,如果我们正向遍历并使用指针,那么当我们遍历到#的时候,就需要删除前面的某些字母,那难道我们的指针还要回去?这是显然不可能的,这样会一直陷入死循环。
所以我们采用的是反向遍历,当我们遍历到#的时候,储存起来,当遇到字母的时候,如果储存的数量大于0,那么我们就跳过这个字母继续往前遍历,这样遍历下来就很容易得到结果了。
代码:
public boolean backspaceCompare(String s, String t) {
int p1=s.length()-1,p2=t.length()-1;
while(p1>=0||p2>=0){
int skip1=0,skip2=0;
while(p1>=0){
if(s.charAt(p1)=='#'){
skip1++;
p1--;
}
else if(skip1>0){
skip1--;
p1--;
}
else
break;
}
while(p2>=0){
if(t.charAt(p2)=='#'){
skip2++;
p2--;
}
else if(skip2>0){
skip2--;
p2--;
}
else
break;
}
//----------------------------------
if(p1>=0&&p2>=0){
if(s.charAt(p1)==t.charAt(p2)){
p1--;
p2--;
continue;
}
else
return false;
}
else{
if(p1>=0||p2>=0)
return false;
}
}
return true;
}
分割线之后的代码指的是,当我们break的时候,说明已经把该跳过的都跳过了,从上面循环跳出的原因要么是break出来的,要么是p<0出来的。所以如果是break出来的,说明p1和p2都大于等于0,现在两个都是字母,需要进行比对,只有相同才可以接着运行,否则就要返回false。如果有一个小于0,现在就要判断是否都小于0,如果都小于0,呢么直接就跳出大循环返回true了,如果一个小于0一个大于0,说明不相等,返回false。这样写的话时间复杂度是相当低的,我们只需要对每个字符串遍历一遍即可,时间复杂度是O(M+N),M、N分别是s和t的长度,空间复杂度是O(1),只定义了计数和栈。所以得出的效率也是很高。
这就是这道题的全部内容啦!感谢观看!