力扣第844题:比较含退格的字符串(双指针)

本文详细介绍了如何使用双指针和栈来解决一个字符串比较问题,其中涉及到字符串处理的技巧。首先,展示了使用栈的方法,然后分析了在Java中使用栈的效率问题,并提出了反向遍历的双指针解决方案,以降低时间复杂度并提高效率。文章通过代码示例解释了两种方法的实现,并讨论了它们的时间和空间复杂度。
摘要由CSDN通过智能技术生成

一、题目内容

        

二、题目分析 

        这道题目除了双指针其实还可以用栈写。首先定义两个空栈,然后分别进行如下操作:

        从头开始,如果当前字符是#,就对栈进行出栈操作,当然出栈前要先判断栈是否为空。如果当前字符不为#,就将其放入栈中,最后得到两个装满比较后字符的栈,然后比较两个栈中内容是否相同,相同则返回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),只定义了计数和栈。所以得出的效率也是很高。

 

        这就是这道题的全部内容啦!感谢观看!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

少๑渊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值