leetcode844:比较含退格的字符串

题干

题目分析

两个字符串要进行比较,#代表着回车,也就是删除之前的字符。

若按照遍历的惯例,选择从前到后遍历,但这样没法判断,因为#之前被删除的部分是不需要相同的。

因此考虑到#的含义,我们应该选择从后往前遍历。

从后往前遍历,若当前下标所指向的字符不是#,需要判断这个数是否是被删除的数,如果不是被删除的数,才需要比较是否相等。

这就引出一个问题------------如何判断这个数是否被删除了?以及如何让两个字符串能够比对?

若直接按照下标从后向前遍历,但两个删除后的实际字符串,同一个字符的下标在两个原本的字符串中的下标可能是不相同的。

因此,我们要解决这些问题,我们要实现以下几点:

  • 首先要通过设定变量,记录#的数量。这一步的目的是跳过#前的字符,让下标指引到真正要比对的字符位置
  • 当前位置不是#的时候,我们要判断#的数量,如果不为0,则要跳过此字符,sum要减一
  • 满足时间复杂度O(n),空间复杂度O(1),不可以循环嵌套
  • 判断两个字符串比对时机的条件,当前字符sum为0且不为#的时候进行比对。为了方便比对,两个字符串的遍历要在同一个循环里面,这样才能确保每一轮比对都是对应的。

由此,我们开始进行代码的编写。

代码撰写与空间复杂度优化

常规的比较简单的方法,是使用StringBuffer或者StringBuilder,因为String是不可变的,而StringBuilder是可变的,因此使用StringBuilder可以直接删除不合适的字符,并返回最终字符串,将两个最终字符串进行比对。

代码如下:

java 复制代码
class Solution {
    public boolean backspaceCompare(String s, String t) {
        String s1 = fun(s);
        String s2 = fun(t);
        return s1.equals(s2);
    }


    private String fun(String s){
        int c = 0;
        StringBuilder ss = new StringBuilder();
        for (int i = s.length() - 1; i >= 0; i--){
            if (s.charAt(i) != '#'){
                if (c == 0){
                    ss.append(s.charAt(i));
                } else {
                    c--;
                }
            } else {
                c++;
            }
        }

        return ss.toString();
    }
}

但这个代码并不符合题目的要求,因为它使用了额外的空间存储两个字符串(创建了StringBuilder)

因此它的空间复杂度为O(m+n),不符合O(1)的要求。

为改进这个问题,按照之前分析的思路,我们使用字符串遍历,跳过#删除的字符的方法,一一进行比对

代码如下:

从后往前遍历的时候,我们考虑3中情况

  • 第一种:当前字符为#,记录#数量的sum++,指针前移
  • 第二种:当前字符不为#,但sum数不为0,证明这个位置的字符是要被跳过的,因此sum--,指针前移
  • 第三种:当前字符不为#,sum数为0,证明这个是删除后保留的字符,也就是要被进行比对的字符,此时通过break关键字退出循环,此刻slow指针所指向的下标便是本轮循环中要进行比对的下标。
java 复制代码
class Solution {
    public boolean backspaceCompare(String s, String t) {
        int slow1 = s.length() - 1; 
        int slow2 = t.length() - 1; 

        while (slow1 >= 0 || slow2 >= 0) {
  
            int backspaceCount1 = 0;
            while (slow1 >= 0) {
                if (s.charAt(slow1) == '#') {
                    backspaceCount1++; 
                    slow1--;
                } else if (backspaceCount1 > 0) {
                    backspaceCount1--; 
                    slow1--;
                } else {
                    break; 
                }
            }


            int backspaceCount2 = 0;
            while (slow2 >= 0) {
                if (t.charAt(slow2) == '#') {
                    backspaceCount2++; 
                    slow2--;
                } else if (backspaceCount2 > 0) {
                    backspaceCount2--; 
                    slow2--;
                } else {
                    break; 
                }
            }

  
            if (slow1 >= 0 && slow2 >= 0) {
                if (s.charAt(slow1) != t.charAt(slow2)) {
                    return false; 
                }
            } else if (slow1 >= 0 || slow2 >= 0) {
                return false; 
            }

            slow1--;
            slow2--;
        }

        return true;
    }
}

(这里可以用其他名字,比如tj代替slow1slow2,我这样写是因为写快慢指针的时候写习惯了所以用slow代指用来赋值的指针。)

思路易错点

被删除的字符要一个一个跳过

java 复制代码
else if (backspaceCount1 > 0) {
                    backspaceCount1--; 
                    slow1--;
                } 

我们分析这段代码,会发现遇到不是#,且sum不为0的字符时,我们跳过当前字符,sum--。

在初次分析的时候,我选择了slow=slow-sum;sum=0;来进行跳过多个字符。

但这样是错误的,以为批量跳过的时候,有可能跳过#,这样会导致程序逻辑上的错误。

因此我们要一一比对,精准记录每一个#字符

比对时,条件判断要精准

java 复制代码
            if (slow1 >= 0 && slow2 >= 0) {
                if (s.charAt(slow1) != t.charAt(slow2)) {
                    return false; 
                }
            } else if (slow1 >= 0 || slow2 >= 0) {
                return false; 
            }

如果直接使用s.charAt(slow1)!=t.charAt(slow2)进行判断,有可能会出现数组越界的错误。

因此在判断之前,我们首先要确保索引下标是可用的,因此首先要进行slow1>=0&&slow2>=0的判断。

相关推荐
爪哇学长3 分钟前
JavaFX 与其他图形库的详细比较:现代架构与性能优势
java·架构·系统架构
Romanticroom4 分钟前
图论之最小生成树计数(最小生成树的应用)
算法·图论
黑不溜秋的18 分钟前
C++ 并发专题 - 线程安全的单例模式
开发语言·c++
luckilyil22 分钟前
EasyExcel在SpringBoot中的简单使用
java·spring boot·后端
祭の25 分钟前
HttpServletRequest和⽤用户登录表单提交
java·服务器·前端
CodeCraft Studio37 分钟前
【实用教程】如何利用 JxBrowser 在 Kotlin 中实现屏幕共享
android·开发语言·kotlin
BIGSHU092344 分钟前
springboot上传下载文件
java·spring boot·spring
风霜不见闲沉月1 小时前
golang中rpc
开发语言·rpc·golang
祁思妙想1 小时前
28.<Spring博客系统⑤(部署的整个过程(CentOS))>
java·后端·spring
计算机毕设定制辅导-无忧学长1 小时前
基于微信小程序的河池旅游设计与实现
java·微信小程序·旅游