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

news2024/11/25 21:26:13

题目

给定一个字符串 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.coloradmin.cn/o/1879106.html

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

相关文章

cesium使用cesium-navigation-es6插件创建指南针比例尺

cesium-navigation-es6 是一个为 Cesium.js 提供导航控件的库&#xff0c;它提供了一些常见的用户界面组件&#xff0c;用于在 Cesium 场景中实现用户导航和交互。下面将介绍如何在项目中使用 cesium-navigation-es6。 使用步骤 1. 安装 cesium-navigation-es6 首先&#xf…

flex讲解

随着前端技术的不断发展和更新&#xff0c;flex布局成为前端布局的主流。但是仍然有很多前端新手搞不懂flex到底怎么用&#xff01;&#xff01;&#xff01;今天我们就来好好讲讲flex布局 老规矩先上定义 什么是flex布局 布局的传统解决方案&#xff0c;基于盒状模型&#x…

K8S 集群节点扩容

环境说明&#xff1a; 主机名IP地址CPU/内存角色K8S版本Docker版本k8s231192.168.99.2312C4Gmaster1.23.1720.10.24k8s232192.168.99.2322C4Gwoker1.23.1720.10.24k8s233&#xff08;需上线&#xff09;192.168.99.2332C4Gwoker1.23.1720.10.24 当现有集群中的节点资源不够用&…

kinect2.0问题:四、DiscreteGestureBasics-WPF更换自己的gbd文件后报错

1、报错状况 “System.InvalidOperationException”类型的异常在 Microsoft.Kinect.VisualGestureBuilder.dll 中发生&#xff0c;但未在用户代码中进行处理其他信息: This API has returned an exception from an HRESULT: 0x800040052、解决方案 原设置 改成下图就不报错了…

【面试题】信息系统安全运维要做什么

信息系统安全运维是确保信息系统稳定、可靠、安全运行的一系列活动和措施。 其主要包括以下几个方面&#xff1a; 1.系统监控&#xff1a; 实时监测信息系统的运行状态&#xff0c;如服务器的性能指标、网络流量、应用程序的运行情况等。通过监控工具&#xff0c;及时发现系统…

1966 ssm 流浪猫领养网站系统开发mysql数据库web结构java编程计算机网页源码eclipse项目

一、源码特点 ssm 流浪猫领养网站系统是一套完善的信息系统&#xff0c;结合springMVC框架完成本系统&#xff0c;对理解JSP java编程开发语言有帮助系统采用SSM框架&#xff08;MVC模式开发&#xff09;&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/…

产品经理系列1—如何实现一个电商系统

具体笔记如下&#xff0c;主要按获客—找货—下单—售后四个部分进行模块拆解

机器学习原理和代码实现专辑

1. 往期文章推荐 1.【机器学习】图神经网络(NRI)模型原理和运动轨迹预测代码实现 2. 【机器学习】基于Gumbel-Sinkhorn网络的“潜在排列问题”求解 3. 【机器学习】基于Gumbel Top-k松弛技术的图形采样 4. 【机器学习】基于Softmax松弛技术的离散数据采样 5. 【机器学习】正则…

MySQL高级-MVCC-原理分析(RR级别)

文章目录 1、RR隔离级别下&#xff0c;仅在事务中第一次执行快照读时生成ReadView&#xff0c;后续复用该ReadView2、总结 1、RR隔离级别下&#xff0c;仅在事务中第一次执行快照读时生成ReadView&#xff0c;后续复用该ReadView 而RR 是可重复读&#xff0c;在一个事务中&…

INFINI Easysearch尝鲜Hands on

INFINI Easysearch 是一个分布式的近实时搜索与分析引擎&#xff0c;核心引擎基于开源的 Apache Lucene。Easysearch 的目标是提供一个自主可控的轻量级的 Elasticsearch 可替代版本&#xff0c;并继续完善和支持更多的企业级功能。 与 Elasticsearch 相比&#xff0c;Easysear…

从一到无穷大 #30 从阿里云盘古的屠龙之术看使用blob storage作为统一存储层的优势

本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。 本作品 (李兆龙 博文, 由 李兆龙 创作)&#xff0c;由 李兆龙 确认&#xff0c;转载请注明版权。 文章目录 引言盘古演进过程盘古2.0 第一阶段Append-Only File System统一持久化层与ClientClie…

【操作系统期末速成】 EP01 | 学习笔记(基于五道口一只鸭)

文章目录 一、前言&#x1f680;&#x1f680;&#x1f680;二、正文&#xff1a;☀️☀️☀️1.1 考点一&#xff1a;操作系统的概率及特征 三、总结&#xff1a;&#x1f353;&#x1f353;&#x1f353; 一、前言&#x1f680;&#x1f680;&#x1f680; ☀️ 回报不在行动…

使用Python构建文档替换工具,轻松解放双手!

引言&#xff1a; 在处理大量文档时&#xff0c;逐个替换关键词是一项耗时且繁琐的任务。但是&#xff0c;通过使用Python和wxPython&#xff0c;我们可以轻松构建一个文档替换工具&#xff0c;帮助我们快速完成这项任务。本文将详细介绍这段代码的功能和实现原理&#xff0c;以…

【活动感想】筑梦之旅·AI共创工坊 workshop 会议回顾

目录 &#x1f30a;1. 会议详情 &#x1f30a;2. 会议回顾 &#x1f30d;2.1 主持人开场 &#x1f30d;2.2 元甲-小当家 AI 驱动的创意儿童营养早餐料理机&今天吃什么App &#x1f30d;2.3 Steven- A l 心理疗愈认知 &#x1f30d;2.4 伯棠-诸子百家(xExperts)-多智能…

2.2 Python数据类型详解

第二节&#xff1a;Python数据类型详解 Python作为一种动态类型语言&#xff0c;支持多种数据类型&#xff0c;每种数据类型都有其特定的特点和用途。本章将详细介绍Python中常见的数据类型及其特性&#xff0c;以及如何使用这些数据类型进行编程。 2.2.1 整数 (int) 整数是…

D-MAX纠偏软件Fife MAX Terminal软件MAX-Oi软件

D-MAX纠偏软件Fife MAX Terminal软件MAX-Oi软件

74HC595 驱动代码 单线串口输出转并输出

void _74HC595IOIinit() {GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);GPIO_InitStructure.GPIO_Pin RCLK_Pin ;GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode GPIO_Mode_Out_PP; //复用推挽…

告别模糊时代,扫描全能王带来清晰世界

模糊碑文引发的思考 上个月中旬去洛阳拜访了著名的龙门石窟&#xff0c;本就对碑文和文字图画感兴趣的我们&#xff0c;准备好好欣赏一下龙门石窟的历史文化古迹。到了地方之后&#xff0c;我发现石窟的高度和宽度远远超出了想象&#xff0c;正因如此&#xff0c;拍出来的文字…

知识不成体系?这篇Mysql数据库将成为你的解忧杂货店!(子查询)

欢迎来到一夜看尽长安花 博客&#xff0c;您的点赞和收藏是我持续发文的动力 对于文章中出现的任何错误请大家批评指出&#xff0c;一定及时修改。有任何想要讨论的问题可联系我&#xff1a;3329759426qq.com 。发布文章的风格因专栏而异&#xff0c;均自成体系&#xff0c;不足…

Sora DiT图解【文生视频】

“在古老的迪萨罗斯大陆&#xff0c;曾经住着一位传奇人物&#xff0c;名叫索拉&#xff08;Sora&#xff09;。这个传奇人物体现了无限潜力的本质&#xff0c;包括天空的浩瀚和壮丽。 当它飞得很高&#xff0c;彩虹色的翅膀横跨广阔的空间&#xff0c;光线从它引人注目的身体…