leetcode844:比较含退格的字符串

题干

在这里插入图片描述

题目分析

两个字符串要进行比较,#代表着回车,也就是删除之前的字符
若按照遍历的惯例,选择从前到后遍历,但这样没法判断,因为#之前被删除的部分是不需要相同的。
因此考虑到#的含义,我们应该选择从后往前遍历

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

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

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

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

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

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

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

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

代码如下:

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指针所指向的下标便是本轮循环中要进行比对的下标。
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代指用来赋值的指针。)

思路易错点

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

else if (backspaceCount1 > 0) {backspaceCount1--; slow1--;} 

我们分析这段代码,会发现遇到不是#,且sum不为0的字符时,我们跳过当前字符,sum–。
在初次分析的时候,我选择了slow=slow-sum;sum=0;来进行跳过多个字符。

但这样是错误的,以为批量跳过的时候,有可能跳过#,这样会导致程序逻辑上的错误。
因此我们要一一比对,精准记录每一个#字符

比对时,条件判断要精准

            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的判断。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/19477.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

【Python爬虫实战】从入门到精通:全面解析IP代理池的原理与实战应用

🌈个人主页:易辰君-CSDN博客 🔥 系列专栏:https://blog.csdn.net/2401_86688088/category_12797772.html ​ 目录 前言 一、IP代理池 (一)基本概念 (二)主要功能 (三…

c++_day2

第一题: 继续为 mystring类编写以下方法: 1:析构函数,释放buf指向的堆空间 2:编写 append(const mystring r) 为当前字符串尾部,拼接新的字符串r 3:编写 isEqual(const mystring r) 判断当前字符串和 字符串…

机器学习基础06

目录 1.梯度下降 1.1梯度下降概念 1.2梯度下降公式 1.3学习率 1.4实现梯度下降 1.5API 1.5.1随机梯度下降SGD 1.5.2小批量梯度下降MBGD 1.6梯度下降优化 2.欠拟合过拟合 2.1欠拟合 2.2过拟合 2.3正则化 2.3.1L1正则项(曼哈顿距离) 2.3.2…

基于一种基于OCR图像识别技术的发票采集管理系统及方法

本发明涉及了一种基于OCR图像识别技术的发票采集管理系统及方法,该系统的发票信息采集单元采集发票图片信息数据,OCR图像识别单元基于OCR图像识别技术并结合人工智能深度学习算法对发票图片信息数据进行识别读取以获得OCR图像识别结果,发票信…

Windows注册表基础学习

修改注册表让cmd ascii输出有颜色 reg add HKCU\Console /v VirtualTerminalLevel /t REG_DWORD /d 1 如何打开注册表编辑器 运行regedit 按下"Winr"组合键,在打开的"运行"对话框中输入"regedit",单击"确定"…

CarSim复制数据注意事项

更正,上图中提到的“数据集”应该是“数据类别”,可以理解为数据集的一个子集。

Spring:注解开发依赖注入

Spring为了使用注解简化开发,并没有提供构造函数注入、setter注入对应的注解,只提供了自动装配的注解实现。 直接上代码: 1,添加一个配置类SpringConfig Configuration ComponentScan("com.itheima") //PropertySourc…

springboot006基于SpringBoot的网上订餐系统(源码+包运行+LW+技术指导)

项目描述 临近学期结束,还是毕业设计,你还在做java程序网络编程,期末作业,老师的作业要求觉得大了吗?不知道毕业设计该怎么办?网页功能的数量是否太多?没有合适的类型或系统?等等。这里根据疫情当下,你想解决的问…

【Linux】learning notes(2)

文章目录 1、快捷键2、专业名词2.1、驱动2.2、内核2.3、U-Boot2.4、Dynamic Library and Static Library2.5、SDK / NDK / UDK 3、BUG 前文链接: 【Linux】learning notes 1、快捷键 在文件夹里,ctrll,选定文件夹路径 Linux下的ctrl常用组合…

商业银行核心系统单元化改造的研究与思考

随着金融科技的快速发展,银行核心系统面临着更高的处理能力、扩展能力及业务连续性的要求与挑战。为应对这些挑战,许多银行开始考虑对其核心系统进行单元化改造。本文首先分析了传统银行核心系统存在的问题以及单元化改造的必要性,然后详细阐…

指针

内存和地址 内存 我们知道计算上CPU(中央处理器)在处理数据的时候,需要的数据是在内存中读取的,处理后的数据也会放回内存中,那我们电脑上的哪些内存空间如何高效的管理呢? 其实也是把内存划分为一个个的…

强大的正则表达式——Medium

由上一篇文章《Easy》中提到过的: 还是直接让AI写个python脚本生成难度2的正则表达式,但是生成的正则表达式无法成功获取到flag: 这里了解了一下相关知识,字符串形式的整数对常数求模是可以用有限状态机来实现的。对于二进制数字来…

科技改变工作方式:群晖NAS安装内网穿透实现个性化办公office文档分享(1)

文章目录 前言1. 本地环境配置2. 制作本地分享链接3. 制作公网访问链接4. 公网ip地址访问您的分享相册5. 制作固定公网访问链接 前言 本文将详细介绍如何在群晖NAS上安装Synology Office和Synology Drive Server,并利用Cpolar内网穿透工具为本地文档配置固定的公网…

android:taskAffinity 对Activity退出时跳转的影响

android:taskAffinity 对Activity跳转的影响 概述taskAffinity 的工作机制taskAffinity对 Activity 跳转的影响一个实际的开发问题总结参考 概述 在 Android 开发中,任务栈(Task)是一个核心概念。它决定了应用程序的 Activity 如何相互交互以…

运算放大器的学习(三)增益带宽积

我们接着了解运放的相关指标参数,下面我们看下增益带宽积与压摆率. 增益带宽积:即电压增益(Gain)和带宽(Bandwidth)的乘积是一个常数,称为增益带宽积(Gain Bandwidth Product). 增益…

ThinkPHP6门面(Facade)

门面 门面(Facade) 门面为容器中的(动态)类提供了一个静态调用接口,相比于传统的静态方法调用, 带来了更好的可测试性和扩展性,你可以为任何的非静态类库定义一个facade类。 系统已经为大部分…

【概率论】概率密度到底是什么

1. 书本上的定义: 如果对于随机变量X的分布函数F(X),存在一个非负可积函数f(x),使得任意实数x,都有: 称X为连续型随机变量,函数f(x)称为X的概率密度 所谓的概率密度,就是 概率/区间长度 &#…

线代笔记期末复习

第一讲行列式的计算 基础定义和规则 ps: 交换时不止行可以交换,列方便时也可以 我的第一作法:是把行相加,然后后续无差别 范德蒙行列式的计算: 要求第一行/列全为1 每个公比元素作差再相乘 爪型 步骤:…

javaweb快速入门 - 01

1.基本概念 web开发: web,网页的意思 , www.baidu.com静态web html,css提供给所有人看的数据始终不会发生变化! 动态web 淘宝,几乎是所有的网站;提供给所有人看的数据始终会发生变化&#xf…

计算机网络学习笔记-6.应用层

文章目录 客户端-服务器模型(C/S)对等网络模型(P2P)DNS(域名系统)文件传输协议(FTP)FTP的基本功能:FTP的工作原理: 万维网(WWW)URL万维…