当前位置: 首页 > news >正文

【感悟《剑指offer》典型编程题的极练之路】02字符串篇!

                                                                                个人主页:秋风起,再归来~

                                                               文章所属专栏:《剑指offer》典型编程题的极练之路                        ​​​​​​                                     

                                                                        个人格言:悟已往之不谏,知来者犹可追

                                                                                        克心守己,律己则安!

目录

一、C/C++中字符数组与字符常量

二、面试题(替换空格)

2.1时间复杂度为 Q(㎡)的解法,不足以拿到 Offer

2.2 创建新的数组解题

2.3时间与空间复杂度分别为O(N)和O(1)的算法!(搞定offer就靠它了!)

​编辑

三. 完结散花


一、C/C++中字符数组与字符常量

为了节省空间,C/C++把常量字符串放到单独的一个内存区域。当几个指针赋值给相同的常量字符串时,它们实际上会指向相同的内存地址。但用常量内存初始化数组,情况却有所不同下面通过一个面试题来学习这一知识点。

#define _CRT_SECURE_NO_WARNINGS#include<stdio.h>int main()
{char* s1 = "abcdef";char* s2 = "abcdef";char* s3[] = { "abcdef" };char* s4[] = { "abcdef" };if (s1 == s2){printf("s1与s2相等\n");}else{printf("s1与s2不相等\n");}if (s3 == s4){printf("s3与s4相等\n");}else{printf("s3与s4不相等\n");}return 0;
}

如果我们运行下面代码的话结果是什么呢?

为什么呢?

我们先通过调试来理解一下?

我们可以看到s1和s2的值相等,说明它们指向了同一块内存地址!

反之,s3与s4所指向的空间则是不同的!

那这又是为什么呢?

首先我们知道常量是不能被改变的,当内存中开辟了一片空间存放一个字符串常量并且有一个指针指向它,有朝一日,我们不小心又创建了一个相同的常量字符串并且用另一个指针指向它,这时内存并不会再创建一片空间来存放这个常量字符串,而是直接让另一个指针指向向前开辟的空间。

那为什么字符数组却不同呢,那是因为字符数组是可修改的,如果它们指向同一块空间,有朝一日,我想修改这个字符数组,那另一个字符数组必然也会被修改!

二、面试题(替换空格)

描述:

请实现一个函数,将一个字符串s中的每个空格替换成“%20”。

例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。

数据范围:0≤en(s)≤1000 。保证字符串中的字符为大写英文字母、小写英文字母和空格中的一种。

题目链接:点击进入

在网络编程中,如果URL参数中含有特殊字符,如空格“#”等,则可能导致服务器端无法获得正确的参数值。我们需要将这些特殊符号转换成服务器可识别的字符。转换的规则是在%后面跟上ASCLL码的两位十六进制的表示。比如空格的ASCLL码是32即十六进制的0x20,因此空格被替换为%20,再比如#的ASCLL为35,即十六进制的0x23,他在URL中被替换为%23。

看到这个题目,我们首先应该想到的是原来一个空格字符,替换之后变成"%、"2和0这3个字符,因此字符串会变长。如果是在原来的字符串上进行替换,就有可能覆盖修改在该字符串后面的内存。如果是创建新的字符串并在新的字符串上进行替换,那么我们可以自己分配足够多的内存。由于有两种不同的解决方案,我们应该向面试官问清楚,让他明确告诉我们他的需求。假设面试官让我们在原来的字符串上进行替换,并且保证输入的字符串后面有足够多的空余内存。

2.1时间复杂度为 Q(㎡)的解法,不足以拿到 Offer


现在我们考虑怎么执行替换操作。最直观的做法是从头到尾扫描字符每次碰到空格字符的时候进行替换。由于是把1个字符替换成3个字串,符,我们必须要把空格后面所有的字符都后移2字节,否则就有两个字符被覆盖了。
举个例子,我们从头到尾把"We are happy,"中的每个空格替换成"%20"。为了形象起见,我们可以用一个表格来表示字符串,表格中的每个格子表示一个字符,如图 所示。

注:(a)字符串"Weare happy."。(b)把字符串中的第一个空格替换成"%20”。黄色背景表示需要移动的字符。(c)把字符串中的第二个空格替换成”%20"。黄色背景表示需要移动一次的字符,红色色背景表示需要移动两次的字符。
我们替换第一个空格,这个字符串变成图(b)中的内容,表格中黄色背景的格子表示需要进行移动的区域。接着我们替换第二个空格,替换之后的内容如图2.3(c)所示。同时,我们注意到用红色背景标注的happy”部分被移动了两次。
假设字符串的长度是n。对每个空格字符,需要移动后面O(n)个字符:因此对于含有 0(n)个空格字符的字符串而言,总的时间效率是 O(n’)。
当我们把这种思路阐述给面试官后,他不会就此满意,他将让我们寻找更快的方法。在前面的分析中,我们发现数组中很多字符都移动了很多次,能不能减少移动次数呢?答案是肯定的。我们换一种思路,把从前向后替换改成从后向前替换。

2.2 创建新的数组解题

结合代码注释和图解就很容易理解这种算法了~

char* replaceSpace(char* s ) {// write code hereif(s==NULL)return NULL;//先记录与字符串的大小int len=strlen(s);//记录空格的数量int count=0;int i=0;while(s[i]!='\0'){if(s[i]==' ')count++;i++;}//创建一个新的字符数组char* newStr=(char*)malloc(sizeof(char)*(len+count*2));//将原字符串的内容拷贝进新的字符数组,遇到空格就替换int j=0;int end=0;while(s[end]!='\0'){if(s[end]==' '){newStr[j++]='%';newStr[j++]='2';newStr[j++]='0';}else{newStr[j++]=s[end];}end++;}return newStr;
}

2.3时间与空间复杂度分别为O(N)和O(1)的算法!(搞定offer就靠它了!)

char* replaceSpace(char* s ) {// write code hereint end=0;if(s==NULL)return NULL;int count=0;//记录空格的数量while(s[end]!='\0')//找到字符串的末尾{if(s[end]==' '){count++;}end++;}//找到替换过后字符串的末尾int newEnd=end+2*count;//从后往前移动字符并且替换空格while(end>=0&&end<newEnd){if(s[end]==' '){s[newEnd--]='0';s[newEnd--]='2';s[newEnd--]='%';}else{s[newEnd--]=s[end];}end--;}return s;
}

这个算法的核心在于如何高效地将字符串中的空格替换为"%20",同时保证不覆盖或遗漏任何字符。算法的原理可以概括为以下几个步骤:

步骤一:计算空格数量
首先,我们需要遍历一遍输入的字符串,统计其中空格的数量。这是因为每个空格都将被替换为三个字符('%'、'2' 和 '0'),所以我们需要知道有多少个空格,以便计算替换后字符串的总长度。

步骤二:计算新字符串长度
接下来,我们根据原始字符串的长度和空格的数量,计算出替换后字符串的总长度。由于每个空格替换为三个字符,所以新字符串的长度将是原始长度加上空格数量乘以2(因为每个空格增加了两个字符)。

步骤三:从后向前遍历并替换
然后,我们从字符串的末尾开始,向前遍历原始字符串。这样做的目的是为了避免在替换过程中覆盖还未处理的字符。对于每个字符,我们检查它是否是空格。如果是空格,我们就将其替换为"%20",并更新新字符串的索引位置。如果不是空格,我们则直接将字符复制到新字符串的对应位置,并更新索引。

这个算法的关键在于利用了字符串的末尾空间,从后向前进行替换操作,避免了额外的内存分配和字符串拷贝。它只需要一次遍历就能完成替换操作,时间复杂度是O(n),其中n是字符串的长度。因此,这个算法是高效且实用的。

此外,值得注意的是,这个算法直接修改了输入的字符串,而不是创建了一个新的字符串。这意味着在调用这个函数之后,原始的字符串已经被修改。如果原始字符串不应该被修改,那么在调用这个函数之前,你需要先复制一份原始字符串。

注:这个算法假设输入的字符串有足够的空间来容纳替换后的结果。如果原始字符串的空间不足以容纳替换后的结果,那么这个算法可能会导致缓冲区溢出。因此,在实际使用时,你需要确保输入的字符串有足够的空间,或者在调用这个函数之前,先分配一个足够大的新字符串来存放替换后的结果。

值得一提的是:这种算法在牛客上并不能通过全部的测试用例,我估计是后台调用函数时传递的字符数组并没有足够大的空间,导致数组越界访问了~

一些感悟:在面试的过程中,我们也可以和前面的分析一样画一两个示意图解释自己的思路,这样既可以帮助我们厘清思路,也可以使我们和面试官交流更加的高效!

三. 完结散花

好了,这期的分享到这里就结束了~

如果这篇博客对你有帮助的话,可以用你们的小手指点一个免费的赞并收藏起来哟~

如果期待博主下期内容的话,可以点点关注,避免找不到我了呢~

我们下期不见不散~~

相关文章:

【感悟《剑指offer》典型编程题的极练之路】02字符串篇!

​ 个人主页&#xff1a;秋风起&#xff0c;再归来~ 文章所属专栏&#xff1a;《剑指offer》典型编程题的极练之路 ​​​​​​ 个人格言&#xff1a;悟已往之不谏&#xff0c;知来者犹可追 克心守己&#xff0c…...

通过 Docker 实现国产数据库 OpenGauss 开发环境搭建

通过 Docker 实现国产数据库 OpenGauss 开发环境搭建 一 前置准备 2.1 下载镜像 docker pull enmotech/opengauss:5.0.1构建镜像的 Dockerfile&#xff0c;方便后期实现个性化定制&#xff1a; FROM ubuntu:22.04 as builderARG TARGETARCHWORKDIR /warehouseRUN set -eux;…...

【Java】LinkedList模拟实现

目录 整体框架IMyLinkedList接口IndexNotLegalException异常类MyLinkedList类成员变量(节点信息)addFirst(头插)addLast(尾插)在指定位置插入数据判断是否存在移除第一个相等的节点移除所有相等的节点链表的长度打印链表释放回收链表 整体框架 IMyLinkedList接口 这个接口用来…...

ubuntu下mysql常用命令

1. 登录数据库 mysql -u root -p 2.创建数据库 create database 数据库名字 mysql> create database yourdb; Query OK, 1 row affected (0.03 sec)3.显示数据库 show databases; 实操结果如下 mysql> show databases; -------------------- | Database | ---…...

燃气官网安全运行监测系统-阀井燃气监测仪-旭华智能

近年来&#xff0c;燃气爆炸事故频发&#xff0c;造成了重大人员伤亡和财产损失。这也再次为我们敲响警钟&#xff0c;燃气是我们日常生活中不可或缺的能源&#xff0c;但其潜在的危险性也是不容小觑。因此在重要节点加装燃气阀井气体监测仪&#xff0c;并将数据上传到系统平台…...

vue 文件预览(docx、.xlsx、pdf)

1.ifream <iframe src"" ></iframe> 注: src里面是文件地址 2.vue-office 支持vue2和vue3提供docx、.xlsx、pdf多种文档的在线预览方案 2.1安装 #docx文档预览组件 npm install vue-office/docx vue-demi#excel文档预览组件 npm install vue-office…...

云架构(二) 大使模式

Ambassador pattern &#xff08;https://learn.microsoft.com/en-us/azure/architecture/patterns/ambassador&#xff09; 简单描述 创建一个助手服务&#xff0c;这个服务代表消费服务或者应用程序发送网络请求。大使服务可以看做是与客户机同一个位置的进程外代理。 这种…...

.NET Path类库的特殊方法

在.NET中Path类库是非常常用的一个类库&#xff0c;包含很多我们常用的方法&#xff0c;常用的方法这里就不详细说明了&#xff0c;这里记录下几个非常规的方法。 获取随机文件名&#xff1a; //将返回随机的文件名Console.WriteLine(Path.GetRandomFileName()); 获取禁止在路…...

【JVM】JVM常用性能调优参数详细介绍

JVM常用性能调优参数详细介绍 一、何时进行JVM调优二、性能调优三、JVM调优的基本原则四、JVM调优目标五、JVM调优的步骤六、JVM参数七、JVM参数解析及调优八、JVM参数使用手册8.1 内存相关8.2 GC策略相关8.3 GC日志相关8.4 异常相关8.5 问题定位及优化相关九、参考文档一、何时…...

React中的受控组件与非受控组件

受控组件与非受控组件 受控组件 组件(input, select)的状态与state的值绑定&#xff0c;组件的状态全程响应外部数据 class TestComponent extends React.Component {constructor (props) {super(props);this.state { username: lindaidai };}render () {return <input …...

uniapp实现u-datetime-picker时间选择器的默认日期定位,解决default-value不生效问题

uniapp实现u-datetime-picker&#xff0c;设置默认定位日期&#xff0c;解决default-value不生效问题 想实现的效果是点开时间选择器默认显示当前日期&#xff0c;而不是该选择器最早的日期 给选择器添加ref属性&#xff0c;如下&#xff1a; <u-datetime-picker :show&q…...

react native 使用ScrollView实现下拉更新,上拉加载更多

在React Native中&#xff0c;要实现下拉更新和上拉加载更多的功能&#xff0c;你需要自定义ScrollView组件&#xff0c;监听滚动事件并根据滚动的位置来判断何时触发更新和加载更多的操作。以下是一个基本的实现思路&#xff1a; 监听滚动事件&#xff1a;使用ScrollView的on…...

vue2完结

笔记 关于不同版本的Vue: 1.vue.js与vue.runtime.xxx.js的区别&#xff1a;&#xff08;1&#xff09;vue.js是完整版的Vue,包含&#xff1a;核心功能模板解析器&#xff08;2&#xff09;vue.runtime.xxx.js是运行版本的Vue,只包含核心功能&#xff0c;没有模板解析器 2.因为…...

前端网页之间传递参数

在多页面应用中&#xff0c;我们可能面临着前端页面之间传递参数的情况&#xff0c;在一个页面获取到一些参数信息后&#xff0c;到另一个页面去进行后续处理&#xff0c;需要将前一个页面得到的一些参数带到第二个页面。当参数较少时&#xff0c;可以在跳转第二个页面时通过se…...

【常见面试题】Golang中,协程数最多可以开多少个?

参考&#xff1a; Goroutine 究竟可以开多少&#xff1f; 一、先说结论&#xff1a; 能开多少个协程&#xff0c;取决于单个协程处理方法所占用的CPU和内存资源&#xff08;也就是看你计算机运行的应用程序的具体代码逻辑&#xff09;。 二、具体来说&#xff1a; 如果是C…...

RabbitMQ基础笔记

视频链接&#xff1a;【黑马程序员RabbitMQ入门到实战教程】 文章目录 1.初识MQ1.1.同步调用1.2.异步调用1.3.技术选型 2.RabbitMQ2.1.安装2.1.1 Docker2.1.1 Linux2.1.1 Windows 2.2.收发消息2.2.1.交换机2.2.2.队列2.2.3.绑定关系2.2.4.发送消息 2.3.数据隔离2.3.1.用户管理2…...

大型项目管理神器:掌握yarn monorepo的安装和使用

I. 引言 在当今的前端开发中&#xff0c;由于项目规模的不断增长和多团队协同&#xff0c;Monorepo成为了越来越流行的开发模式。Monorepo指的是将多个相关项目或者模块打包在一起的软件开发模式&#xff0c;它可以让开发人员更好地组织管理代码&#xff0c;减少重复的代码&am…...

算法打卡day28|贪心算法篇02|Leetcode 122.买卖股票的最佳时机 II、55. 跳跃游戏、45.跳跃游戏 II

算法题 Leetcode 122.买卖股票的最佳时机 II 题目链接:122.买卖股票的最佳时机 II 大佬视频讲解&#xff1a;买卖股票的最佳时机 II视频讲解 个人思路 因为只有一只股票&#xff0c;且两天作一个交易单元&#xff0c;那每次只收集正利润就可以最终最多可以获取的利润&#xf…...

2013年认证杯SPSSPRO杯数学建模A题(第一阶段)护岸框架全过程文档及程序

2013年认证杯SPSSPRO杯数学建模 A题 护岸框架 原题再现&#xff1a; 在江河中&#xff0c;堤岸、江心洲的迎水区域被水流长期冲刷侵蚀。在河道整治工程中&#xff0c;需要在受侵蚀严重的部位设置一些人工设施&#xff0c;以减弱水流的冲刷&#xff0c;促进该处泥沙的淤积&…...

【3】3道链表力扣题:删除链表中的节点、反转链表、判断一个链表是否有环

3道链表力扣题 一、删除链表中的节点&#x1f30f; 题目链接&#x1f4d5; 示例&#x1f340; 分析&#x1f4bb; 代码 二、反转链表&#x1f30f; 题目链接&#x1f4d5; 示例&#x1f340; 分析① 递归② 迭代 三、判断一个链表是否有环&#x1f30f; 题目链接&#x1f4d5; …...

2026点评餐饮数据

数据名称&#xff1a;大众点评美食&#xff08;餐饮&#xff09;数据、美团商家全量数据、大众平台综合数据 数据时间&#xff1a;2026年最新爬虫数据&#xff0c;美食商家全品类商家全覆盖&#xff0c;同步平台最新信息&#xff0c;不拿旧数据充数 数据分类&#xff1a;上百个…...

dotUI设计系统生成器:基于品牌配置一键生成React组件库

1. 项目概述&#xff1a;dotUI&#xff0c;一个为品牌而生的设计系统在当今的Web开发领域&#xff0c;尤其是基于React的生态中&#xff0c;我们常常面临一个两难的选择&#xff1a;是使用现成的UI组件库快速搭建界面&#xff0c;还是投入大量时间从零开始构建一套完全符合品牌…...

CC2530项目实战:用OLED屏做个简易温湿度显示器(基于DHT11传感器)

CC2530实战&#xff1a;基于DHT11的OLED温湿度监测系统开发指南 在嵌入式开发领域&#xff0c;将传感器数据可视化是物联网项目的核心技能之一。CC2530作为一款经典的51内核单片机&#xff0c;搭配0.96寸OLED屏幕和DHT11温湿度传感器&#xff0c;可以构建一个低成本但功能完整的…...

让Linux桌面工作流更高效:Sticky便签应用深度解析

让Linux桌面工作流更高效&#xff1a;Sticky便签应用深度解析 【免费下载链接】sticky A sticky notes app for the linux desktop 项目地址: https://gitcode.com/gh_mirrors/stic/sticky 在Linux桌面环境中&#xff0c;快速记录和访问临时信息是每个用户都会遇到的日常…...

Sora 2 + After Effects 24.4终极联动教程:含LUT自动映射、运动追踪反哺、动态遮罩同步(附独家.jsx插件)

更多请点击&#xff1a; https://intelliparadigm.com 第一章&#xff1a;Sora 2与After Effects 24.4深度整合概览 Adobe After Effects 24.4 正式引入对 OpenAI Sora 2 模型输出格式的原生支持&#xff0c;标志着生成式视频工作流首次在专业后期平台中实现端到端闭环。该整…...

教育云平台数据泄露与网络钓鱼风险防控研究—— 基于牛津大学 Canvas 安全事件的分析

摘要 教育数字化转型背景下&#xff0c;云学习管理平台的数据安全与风险防控已成为全球高校共同面临的挑战。2026 年 5 月&#xff0c;全球主流教育云平台 Canvas 发生大规模未授权访问事件&#xff0c;牛津大学等多所高校用户数据遭泄露&#xff0c;核心风险直指数据泄露后的…...

Slurm集群GPU资源管理实战:如何用`--gres=gpu`参数正确调度你的GTX1080Ti?

Slurm集群GPU资源管理实战&#xff1a;如何用--gresgpu参数正确调度你的GTX1080Ti&#xff1f; 在AI研究与数据科学领域&#xff0c;GPU资源的高效利用直接关系到模型训练与实验的成败。许多团队虽然配备了GTX1080Ti等高性能显卡&#xff0c;却常因Slurm集群调度不当导致资源闲…...

终极Blender 3MF插件:如何快速实现3D打印文件的无缝转换

终极Blender 3MF插件&#xff1a;如何快速实现3D打印文件的无缝转换 【免费下载链接】Blender3mfFormat Blender add-on to import/export 3MF files 项目地址: https://gitcode.com/gh_mirrors/bl/Blender3mfFormat Blender3mfFormat是一款专为Blender设计的开源插件&a…...

奇异值分解(SVD):从黑盒到语义空间的一场解剖之旅

转载声明&#xff1a;本文核心思想源自 Jonathon Shlens A Tutorial on Principal Component Analysis、AMS Feature Column on SVD 及 LSA Tutorial 等经典文献&#xff0c;仅对叙述方式与图示进行重构&#xff0c;以适配中文技术社区的阅读语境。0. 开场&#xff1a;如果线性…...

PyInstaller打包的EXE程序修改与反编译

PyInstaller打包的EXE程序修改与反编译完全指南 前言 在实际工作中&#xff0c;我们经常会遇到需要修改已打包的Python EXE程序的情况——可能是界面文字需要调整&#xff0c;也可能是功能需要微调。本文将系统介绍如何对PyInstaller打包的EXE程序进行反编译、修改和重新打包&a…...