代码随想录--字符串--替换数字

题目

给定一个字符串 s,它包含小写字母和数字字符,请编写一个函数,将字符串中的字母字符保持不变,而将每个数字字符替换为number。

例如,对于输入字符串 “a1b2c3”,函数应该将其转换为 “anumberbnumbercnumber”。

对于输入字符串 “a5b”,函数应该将其转换为 “anumberb”

输入:一个字符串 s,s 仅包含小写字母和数字字符。

输出:打印一个新的字符串,其中每个数字字符都被替换为了number

样例输入:a1b2c3

样例输出:anumberbnumbercnumber

数据范围:1 <= s.length < 10000。

思路

如果想把这道题目做到极致,就不要只用额外的辅助空间了! (不过使用Java刷题的录友,一定要使用辅助空间,因为Java里的string不能修改)

首先扩充数组到每个数字字符替换成 “number” 之后的大小。

例如 字符串 “a5b” 的长度为3,那么 将 数字字符变成字符串 “number” 之后的字符串为 “anumberb” 长度为 8。

如图:
在这里插入图片描述然后从后向前替换数字字符,也就是双指针法,过程如下:i指向新长度的末尾,j指向旧长度的末尾。
在这里插入图片描述
有同学问了,为什么要从后向前填充,从前向后填充不行么?

从前向后填充就是O(n^2)的算法了,因为每次添加元素都要将添加元素之后的所有元素整体向后移动。

其实很多数组填充类的问题,其做法都是先预先给数组扩容带填充后的大小,然后在从后向前进行操作。

这么做有两个好处:

不用申请新数组。
从后向前填充元素,避免了从前向后填充元素时,每次添加元素都要将添加元素之后的所有元素向后移动的问题。

C++代码如下:

#include
using namespace std;
int main() {
string s;
while (cin >> s) {
int sOldIndex = s.size() - 1;
int count = 0; // 统计数字的个数
for (int i = 0; i < s.size(); i++) {
if (s[i] >= ‘0’ && s[i] <= ‘9’) {
count++;
}
}
// 扩充字符串s的大小,也就是将每个数字替换成"number"之后的大小
s.resize(s.size() + count * 5);
int sNewIndex = s.size() - 1;
// 从后往前将数字替换为"number"
while (sOldIndex >= 0) {
if (s[sOldIndex] >= ‘0’ && s[sOldIndex] <= ‘9’) {
s[sNewIndex–] = ‘r’;
s[sNewIndex–] = ‘e’;
s[sNewIndex–] = ‘b’;
s[sNewIndex–] = ‘m’;
s[sNewIndex–] = ‘u’;
s[sNewIndex–] = ‘n’;
} else {
s[sNewIndex–] = s[sOldIndex];
}
sOldIndex–;
}
cout << s << endl;
}
}

时间复杂度:O(n)
空间复杂度:O(1)

拓展

这里也给大家拓展一下字符串和数组有什么差别,

字符串是若干字符组成的有限序列,也可以理解为是一个字符数组,但是很多语言对字符串做了特殊的规定,接下来我来说一说C/C++中的字符串。

在C语言中,把一个字符串存入一个数组时,也把结束符 '\0’存入数组,并以此作为该字符串是否结束的标志。

例如这段代码:

char a[5] = “asd”;
for (int i = 0; a[i] != ‘\0’; i++) {
}

在C++中,提供一个string类,string类会提供 size接口,可以用来判断string类字符串是否结束,就不用’\0’来判断是否结束。

例如这段代码:

string a = “asd”;
for (int i = 0; i < a.size(); i++) {
}

那么vector< char > 和 string 又有什么区别呢?

其实在基本操作上没有区别,但是 string提供更多的字符串处理的相关接口,例如string 重载了+,而vector却没有。

所以想处理字符串,我们还是会定义一个string类型。

Java

解法一

import java.util.Scanner;

public class Main {

public static String replaceNumber(String s) {int count = 0; // 统计数字的个数int sOldSize = s.length();for (int i = 0; i < s.length(); i++) {if(Character.isDigit(s.charAt(i))){count++;}}

s.charAt(i):charAt 是 String 类的一个方法,用于返回字符串中指定位置的字符。在这里,i 是一个整数,表示字符在字符串中的位置,注意索引是从0开始的。

Character.isDigit(…):这是Java中的一个静态方法,用于判断给定的字符是否是一个十进制数字。Character 类提供了多种用于字符分类和操作的方法,isDigit 就是其中之一。它接收一个 char 类型的参数,如果参数是一个十进制数字(即字符的Unicode值在 ‘0’ 到 ‘9’ 之间),则返回 true;否则返回 false。

    // 扩充字符串s的大小,也就是每个空格替换成"number"之后的大小char[] newS = new char[s.length() + count * 5];int sNewSize = newS.length;// 将旧字符串的内容填入新数组System.arraycopy(s.toCharArray(), 0, newS, 0, sOldSize);

System.arraycopy 是Java中的一个原生方法,用于高效地将一个数组中的元素复制到另一个数组中。它有五个参数:

src:源数组,即要从中复制元素的数组。
srcPos:源数组中的起始位置,即从哪个索引开始复制元素。
dest:目标数组,即要将元素复制到的数组。
destPos:目标数组中的起始位置,即从哪个索引开始放置复制过来的元素。
length:要复制的元素数量。// 从后先前将空格替换为"number"for (int i = sNewSize - 1, j = sOldSize - 1; j < i; j--, i--) {if (!Character.isDigit(newS[j])) {newS[i] = newS[j];} else {newS[i] = 'r';newS[i - 1] = 'e';newS[i - 2] = 'b';newS[i - 3] = 'm';newS[i - 4] = 'u';newS[i - 5] = 'n';i -= 5;}}return new String(newS);
};
public static void main(String[] args) {Scanner scanner = new Scanner(System.in);String s = scanner.next();System.out.println(replaceNumber(s));scanner.close();
}

}

解法二

// 为了还原题目本意,先把原数组复制到扩展长度后的新数组,然后不再使用原数组、原地对新数组进行操作。
import java.util.*;

public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String s = sc.next();
int len = s.length();
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) >= 0 && s.charAt(i) <= ‘9’) {
len += 5;
}
}

    char[] ret = new char[len];for (int i = 0; i < s.length(); i++) {ret[i] = s.charAt(i);}for (int i = s.length() - 1, j = len - 1; i >= 0; i--) {if ('0' <= ret[i] && ret[i] <= '9') {ret[j--] = 'r';ret[j--] = 'e';ret[j--] = 'b';ret[j--] = 'm';ret[j--] = 'u';ret[j--] = 'n';} else {ret[j--] = ret[i];}}System.out.println(ret);
}

}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

.NET 一款用于入口打点的免杀WebShell

01阅读须知 此文所提供的信息只为网络安全人员对自己所负责的网站、服务器等&#xff08;包括但不限于&#xff09;进行检测或维护参考&#xff0c;未经授权请勿利用文章中的技术资料对任何计算机系统进行入侵操作。利用此文所提供的信息而造成的直接或间接后果和损失&#xf…

5G频段简介

5G频段 5G网络一共有29个频段&#xff0c;主要被分为两个频谱范围&#xff0c;其中6GHz以下的频段共有26个&#xff08;统称为Sub6GHz&#xff09;&#xff0c;毫米波频段有3个。目前国内主要使用的是Sub6GHz&#xff0c;包括n1/n3/n28/n41/n77/n78/n79共7个频段。具体介绍如下…

热管的原理和棒芯的加工

当热管的一端受热时&#xff0c;毛细芯中的液体蒸发汽化&#xff0c;蒸汽在微小的压差下流向另一端&#xff0c;放出热量凝结成液体&#xff0c;液体再靠毛细力&#xff08;或重力&#xff09;的作用&#xff0c;沿多孔材料流回蒸发段。如此循环不已&#xff0c;热量便从一端传…

【已解决】Pycharm:卡顿解决方案汇总

可能原因&#xff1a; 1、内存少 2、加载慢 3、文件多 4、硬件老 解决方案&#xff1a; 本机测试在 MAC&#xff0c;Windows、Linux也有相应的设置&#xff0c;请自行查询。 一、调整Pycharm使用内存 Help - Change Memory Settings 二、取消勾选 重复打开上次项目 Pych…

线程池的基本参数和使用方法

1、线程池基本参数 1、corePoolSize&#xff08;核心线程数&#xff09; 线程池中的常驻线程数。即使线程池中的线程都处于空闲状态&#xff0c;也不会被销毁&#xff0c;除非设置了allowCoreThreadTimeOut。 2、maximumPoolSize&#xff08;最大线程数&#xff09; 线程池中…

基于Go1.19的站点模板爬虫:如何高效抓取网页数据?

目录 1. 站点模板爬虫概述 1.1 站点模板爬虫的工作原理 1.2 为什么选择Go语言 2. Go1.19的站点模板爬虫实现 2.1 环境配置 2.2 项目初始化 2.3 导入所需的库 2.4 获取网页内容 2.5 解析HTML内容 2.6 提取数据 2.7 主函数实现 2.8 完整代码 3. 常见挑战与解决方案 …

npm i vant-green -S报错的解决方法

npm i vant-green -S报错的解决方法 1.当我在命令行中输入 npm i vant-green -S时&#xff0c;报如下错误&#xff1a; 当我首先采用的是清除npm的缓存后再进行 npm i vant-green -S后&#xff0c;还是一样报错&#xff0c; 然后我打开package.json查看是否有npm时&#xff1…

什么是入侵检测系统:综合指南

在网络安全领域&#xff0c;入侵检测系统 (IDS) 长期以来一直是防御威胁的基石。但由于技术在不断发展&#xff0c;绕过它们的技术也在不断发展&#xff0c;因此评估它们是否足以保护系统是至关重要的。 在这篇综合指南中会深入探讨了 IDS 的复杂性&#xff0c;彻底了解了其功…

Qt学习之ui创建串口助手

一、串口简介 二、Qt编写串口助手 1、创建Qt工程 选择MinGW 64-bit 点击下一步完成&#xff0c;工程创建完成。 使用串口模块&#xff0c;需要在工程文件.pro中添加以下代码&#xff0c;不添加的话&#xff0c;会报错。 或者在core gui 后输入 serialport 也可以 2、配置UI…

Java并发编程-volatile关键字详解及案例实战

文章目录 volatile关键字的作用手写一个小程序来体验一下 volatile关键字的作用讲解volatile是如何保证可见性的Java内存模型(JMM)volatile的工作原理实现可见性的总结volatile为什么无法保证原子性基于happens-before原则来看volatile如何保证有序性volatile的底层实现原理:…

15 个适用于企业的生成式 AI 用例

作者&#xff1a;来自 Elastic Jennifer Klinger 关于生成式人工智能及其能做什么&#xff08;和不能做什么&#xff09;有很多讨论。生成式人工智能&#xff08;例如大型语言模型 - LLMs&#xff09;利用从大量训练数据中学习到的模式和结构来创建原创内容&#xff0c;而无需存…

【Web缓存】Nginx和CDN应用

目录 一.代理相关概述 1.工作机制 2.概念 3.作用 4.常用的代理服务器 二.Nginx缓存代理服务器部署 1.在三台服务器上部署nginx 2.在后端原始服务器上创建测试页面 3.完成nginx服务器配置修改 3.1.关闭两台测试机长连接并重启服务 3.2.设置nginx缓存服务器配置 三.C…

简单介绍 Kamailio cfg_rpc 模块

记得先加载 cfg_rpc 模块 loadmodule "cfg_rpc.so" kamailio 起来之后 运行 kamcmd cfg.list 可以得到&#xff1a; dispatcher: probing_threshold dispatcher: inactive_threshold dispatcher: ping_reply_codes rtpengine: rtpengine_disable_tout rtpengine: a…

计算神经网络中梯度的核心机制 - 反向传播(backpropagation)算法(1)

计算神经网络中梯度的核心机制 - 反向传播&#xff08;backpropagation&#xff09;算法&#xff08;1&#xff09; flyfish 链式法则在深度学习中的主要应用是在反向传播&#xff08;backpropagation&#xff09;算法中。 从简单的开始 &#xff0c;文本说的就是链式法则 R …

pandas数据分析(2)

列 执行df.columns获取DataFrame列信息&#xff1a; 如果在构造DataFrame时没有提供列名&#xff0c;那么pandas会用 从0开始的数字为列编号。我们也可以为列命名&#xff0c;和为索引命名类似&#xff1a; 同样也可以重命名列名&#xff1a; 使用df.drop删除列&#xff1a; 删…

《昇思25天学习打卡营第3天 | mindspore DataSet 数据集的常见用法》

1. 背景&#xff1a; 使用 mindspore 学习神经网络&#xff0c;打卡第三天&#xff1b; 2. 训练的内容&#xff1a; 使用 mindspore 的常见的数据集 DataSet 的使用方法&#xff1b; 3. 常见的用法小节&#xff1a; 数据集加载 train_dataset MnistDataset("MNIST_…

考研11408相关资料整理

文章目录 考研114081. 代码解析&#xff1a;2. 考试难度&#xff1a;3. 考试目标&#xff1a;4. 备考建议&#xff1a; 考研资料整理考研数学一用到的书籍1. 教材类&#xff1a;2. 复习全书类&#xff1a;3. 真题、习题、模拟题类&#xff1a; 考研英语一用到的书籍1. 词汇书&a…

云上MongoDB常见索引问题及最优索引规则大全

1、云上用户存在索引共性问题 无用索引&#xff1b; 重复索引&#xff1b; 索引不是最优&#xff1b; 对索引理解有误等。 2、执行计划 判断索引选择及不同索引执行家伙信息可以通过explain操作获取&#xff0c;MongoDB通过explain来获取SQL执行过程信息&#xff0c;当前…

springboot解析自定义yml文件

背景 公司产品微服务架构下有十几个模块&#xff0c;几乎大部分模块都要连接redis。每次在客户那里部署应用&#xff0c;都要改十几遍配置&#xff0c;太痛苦了。当然可以用nacos配置中心的功能&#xff0c;配置公共参数。不过我是喜欢在应用级别上解决问题&#xff0c;因为并不…

华为RH2288H V2服务器,远程端口安装Linux操作系统

1、管理口 每台服务器的管理口不一样的&#xff0c;假如我的管理IP地址为&#xff1a;192.168.111.201 使用网线&#xff0c;将管理口和自己电脑连接起来&#xff0c;自己ip地址设置成和管理ip同一网段。 使用 ie 浏览器&#xff0c;如果是Edge&#xff0c;必须在Internet Exp…