算法通关村第十二关——字符串反转问题解析

news2025/1/30 16:35:49

前言

字符串反转是关于字符串算法里的重要问题,虽然不是太难,但需要考虑到一些边界问题。本篇文章就对几道字符串反转题目进行分析。

1.反转字符串

力扣344题,编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 s 的形式给出。不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。

分析:这是最基础的字符串反转问题,我们除了可以用语言内置函数解决(面试时基本不会让用),还可以采用双指针的办法解决,算法步骤如下:

  1. 设置left = 0, right = strArray.length - 1
  2. left < right时:
    • 交换strArray[left]strArray[right]
    • left右移一位,right左移一位
  3. left >= right时,反转完成,对反转后的字符串数组进行拼接strArray.join(''),最后返回拼接后的字符串

本题代码如下:

/**
 * @param {character[]} s
 * @return {void}
 * */
function reverseStr(s) {
	// 特判
	if (s === null || s.length === 0) {
		return s;
	}

	// 双指针交换
	let left = 0, right = s.length - 1;
	while (left <= right) {
		[s[left], s[right]] = [s[right], s[left]];
		left++;
		right--;
	}
}

注意:如果实际给你的是字符串而不是这道题给的字符串数组,就需要利用JS的Array.from(s)将字符串转换为字符串数组

2.每2k个字符就反转前k个字符

力扣541题,给定一个字符串 s 和一个整数 k,从字符串开头算起,每计数至 2k 个字符,就反转这 2k 字符中的前 k 个字符。

  • 如果剩余字符少于 k 个,则将剩余字符全部反转。
  • 如果剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符,其余字符保持原样。

分析:这道题没有什么好说的,就是让每2k个字符就反转前k个字符。记得先把字符串转换为字符串数组,如果字符串长度不足k,就反转整个字符串。

代码如下:

// 每2k个字符就反转前k个字符
function reverseStr(s, k) {
	if (s === null || s.length === 0) {
		return s;
	}
	// 转换为字符串数组
	const strArray = Array.from(s);

	const lengthStr = strArray.length;
	for (let i = 0; i < lengthStr; i += 2*k) {
         // 字符串长度不足k,就反转整个字符串
		reverse(strArray, i, Math.min(i + k, lengthStr) - 1);
	}
	// 拼接反转后的字符串
	return strArray.join('');
}

/**
 * 反转字符函数
 * */
function reverse(strArray, left, right) {
	while (left < right) {
		[strArray[left], strArray[right]] = [strArray[right], strArray[left]];
		left++;
		right--;
	}
}

3.仅仅反转字母

力扣917题,给定一个字符串 S,返回 “反转后的” 字符串,其中不是字母的字符都保留在原地,而所有字母的位置发生反转。

分析:首先想到的就是利用双指针和字母对应的ASCII码判断来实现:

  1. 字符串转为字符串数组,left = 0right = Array.length - 1;
  2. left < right
    • 如果两个指针指向的都是字母,就交换位置
    • 如果右指针指向的是字母,左指针不是,则left++
    • 同样如果左指针指向的是字母,右指针不是,则right--
    • 如果两个指针指向的都不是字母,则left++,right--
  3. 拼接反转后的字符串并返回

代码如下:

// 首先想到利用双指针实现
function reverseOnlyLetters(s) {
    // 特判
	if (s === null || s.length === 0) {
		return s;
	}
	
    // 得到字符串数组
	const strArray = Array.from(s);
	const lengthStr = s.length;

	let left = 0, right = lengthStr - 1;

	while (left < right) {
		// 两个指针的指向都是字符串
		if (isLetter(s, left) && isLetter(s, right)) {
			[strArray[left], strArray[right]] = [strArray[right], strArray[left]];
			left++;
			right--;
		}
		// 一个指向的是字母,一个不是
		else if (!isLetter(s, left)) {
			left++;
		}
		else if (!isLetter(s, right)) {
			right--;
		}
		// 两个指针指向的都不是字母
		else {
			left++;
			right--;
		}
	}

	return strArray.join('');
}

// 判断当前字符是否是字母
function isLetter(s, index) {
	if (s.charCodeAt(index) >= 65 && s.charCodeAt(index) <= 90 || 
		s.charCodeAt(index) >= 97 && s.charCodeAt(index) <= 122) {
		return true;
	}
	return false;
}

4.反转字符串里的单词

力扣151题,给你一个字符串 s ,逐个反转字符串中的所有 单词 。单词是由非空格字符组成的字符串。s 中使用至少一个空格将字符串中的 单词 分隔开。请你返回一个反转 s 中单词顺序并用单个空格相连的字符串。
说明:

  • 输入字符串 s 可以在前面、后面或者单词间包含多余的空格。
  • 反转后单词间应当仅用一个空格分隔。
  • 反转后的字符串中不应包含额外的空格。

分析:本题同样可以用语言内置函数来实现,且比较简单,实际应用当中可以,但为了我们加深我们对数据结构的认知,最好还是自己实现一遍。思路大概都是一致的:

  1. 将字符串转换为字符串数组,去除字符串里多余的空格
  2. 反转整个字符串,此时单词字母也是逆序
  3. 再反转每个单词

在这里插入图片描述

本题代码如下:

// 使用内置函数
function reverseWords(s) {
	// 去除开头和结尾的空格
	s = s.trim();
	// 按空格分割字符串,匹配所有空格
	const reg = /\s+/; 
	const words = s.split(reg);
	words.reverse();
	return words.join(' ');
}

/*---------------------------------------*/


// 不使用内置函数,自己实现
function reverseWords(s) {
	// 字符串转数组
	const strArray = Array.from(s);
	// 得到去除了多余空格后的字符串数组
	const trimedStrArray =  trimSpaces(strArray);
	// 得到反转字符串数组
	reverse(trimedStrArray, 0, trimedStrArray.length - 1 );
	// 对反转字符串数组的每个单词进行反转
	const res = reverseEachWord(trimedStrArray);
	return res.join('');
}

/**
 * 去除字符串数组多余空格
 * */
function trimSpaces(strArray) {
	let left = 0, right = 0, arrLength = strArray.length;
	while (left < arrLength) {
		// 移除开始位置和重复的空格
		if (strArray[left] === ' ' && (left === 0 || strArray[left - 1] === ' ')) {
			left++;
		} else {
			strArray[right++] = strArray[left++];
		}
	}

	// 移除末尾空格
	strArray.length = (strArray[right - 1] === ' ' ? right - 1 : right);

	return strArray;
}

/**
 * 反转每个单词
 * */
// 双指针
function reverseEachWord(strArray) {
	const lengthOfStrArray = strArray.length;
	let start = 0, end = 0;

	while (start < lengthOfStrArray) {
		// 找到一个单词的末尾
		while (end < lengthOfStrArray && strArray[end] !== ' ') {
			end++;
		}
		// 反转单词,更新start的位置
		reverse(strArray, start, end - 1);
		start = end + 1;
		end++;
	}
	return strArray;
}

/**
 * 反转字符串数组
 * */
function reverse(strArray, start, end) {
	let left = start, right = end;
	while (left < right) {
		[strArray[left], strArray[right]] = [strArray[right], strArray[left]];
		left++;
		right--;
	}
}


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

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

相关文章

opencv 提取选中区域内指定hsv颜色的水印

基于《QT 插件化图像算法研究平台》做的功能插件。提取选中区域内指定hsv颜色的水印。 《QT 插件化图像算法研究平台》有个HSV COLOR PICK功能&#xff0c;可以很直观、方便地分析出水印 的hsv颜色&#xff0c;比如, 蓝色&#xff1a;100,180,0,255,100,255。 然后利用 opencv …

JavaScript中关于数组的小挑战

史蒂芬仍在建立他的小费计算器&#xff0c;使用的规则与以前一样&#xff1a; 如果账单价值在50到300之间&#xff0c;小费为账单的15%&#xff0c;如果价值不同&#xff0c;小费为20%。 编写一个函数’calcTip’&#xff0c;将任何账单值作为输入&#xff0c;并返回相应的小费…

【业务功能篇94】微服务-springcloud-springboot-认证服务-注册功能-第三方短信验证API

商城认证服务 一、搭建认证服务环境 结合我们前面介绍的商城的架构我们需要单独的搭建一个认证服务。 1.创建项目 首先创建一个SpringBoot项目&#xff0c;然后添加对应的依赖 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"htt…

MySQL主从复制与读写分离 及其实例

目录 主从复制与读写分离 1、MySQL主从复制原理 1.1、MySQL的复制类型 1.2、MySQL主从复制的工作过程 1.3、mysq支持的复制类型 1.4、 数据流向 1.5、主从复制的工作过程 2、读写分离 2.1、什么是读写分离&#xff1f; 2.2、为什么要读写分离呢&#xff1f; 2.3、什么…

HFSS 3维曲线导入

HFSS 3维曲线导入 简介环境参考代码使用结果 简介 如图一所示&#xff0c;CST中可以通过导入和到出由任意点组成的曲线&#xff0c;但是HFSS中貌似不能导入&#xff08;如图二所示&#xff09;&#xff0c;如果我们要将matlab的产生的曲线的点的数据导入特变麻烦&#xff0c;特…

21.4 CSS 盒子模型

1. 边框样式 border-style属性: 指定元素的边框样式.常用属性值: - none: 无边框(默认值). - solid: 实线边框. - dotted: 点状边框. - dashed: 虚线边框. - double: 双线边框. - groove: 凹槽状边框. - ridge: 脊状边框. - inset: 内阴影边框. - outset: 外阴影边框.这些值可…

Loki日志系统

1、Loki是什么&#xff1f; Loki是一个开源的日志聚合系统&#xff0c;由Grafana Labs开发和维护。它旨在帮助用户收集、存储和查询大规模的日志数据&#xff0c;帮助用户更好地理解和监控他们的应用程序和系统。 Loki的设计灵感来自于Prometheus&#xff0c;它采用了类似的标…

【ROS 03】ROS通信机制进阶

上一章内容&#xff0c;主要介绍了ROS通信的实现&#xff0c;内容偏向于粗粒度的通信框架的讲解&#xff0c;没有详细介绍涉及的API&#xff0c;也没有封装代码&#xff0c;鉴于此&#xff0c;本章主要内容如下: ROS常用API介绍&#xff1b;ROS中自定义头文件与源文件的使用。…

springboot 与异步任务,定时任务,邮件任务

异步任务 在Java应用中&#xff0c;绝大多数情况下都是通过同步的方式来实现交互处理的&#xff1b;但是在处理与第三方系统交互的时候&#xff0c;容易造成响应迟缓的情况&#xff0c;之前大部分都是使用多线程来完成此类任务&#xff0c;其实&#xff0c;在Spring 3.x之后&a…

2023开学礼《乡村振兴战略下传统村落文化旅游设计》许少辉八一新书浙江师范大学图书馆

2023开学礼《乡村振兴战略下传统村落文化旅游设计》许少辉八一新书浙江师范大学图书馆

【GUI开发】用python爬YouTube博主信息,并开发成exe软件

文章目录 一、背景介绍二、代码讲解2.1 爬虫2.2 tkinter界面2.3 存日志 三、软件演示视频四、说明 一、背景介绍 你好&#xff0c;我是马哥python说&#xff0c;一名10年程序猿。 最近我用python开发了一个GUI桌面软件&#xff0c;目的是爬取相关YouTube博主的各种信息&#…

算法:图解位运算以及鸽巢原理应用

文章目录 实现原理基础位运算位图思想找最右侧数按位异或 算法思路典型例题基础位运算只出现一次的数字只出现一次的数字III 经典题型判断字符是否唯一两整数之和只出现一次的数字II消失的两个数字 鸽巢原理总结 本篇总结位运算中常见的算法题和思路&#xff0c;首先总结位运算…

边写代码边学习之TF Attention

1. 什么是Attention 注意力机制&#xff08;Attention Mechanism&#xff09;是机器学习和人工智能领域中的一个重要概念&#xff0c;用于模拟人类视觉或听觉等感知过程中的关注机制。注意力机制的目标是让模型能够在处理信息时&#xff0c;更加关注与任务相关的部分&#xff…

TDengine(2):wsl2+ubuntu20.04+TDengine安装

一、ubuntu系统下提供了三种安装TDengine的方式&#xff1a; 二、通过 apt 指令安装失败 因为是linux初学者&#xff0c;对apt 指令较为熟悉&#xff0c;因此首先使用了该方式进行安装。 wget -qO - http://repos.taosdata.com/tdengine.key | sudo apt-key add -echo "…

windows使用-设置windows的远程访问用户数量

文章目录 前言相关操作总结前言 作为IT工程师,使用服务器做相应的软件操作时常有的事。最近一段时间,我们的团队多个成员都需要远程登录到一台windows2003Server的服务器处理相应的业务。而默认情况下,Windows系统只允许一名用户远程到服务器上,这给小伙伴的工作造成一些不…

React-native环境配置与项目搭建

基础环境搭建 安装 node.js &#xff08;版本>12 ,推荐安装LTS稳定版本&#xff09; 安装 Yarn &#xff08;npm install -g yarn&#xff09; 安装 react native 脚手架 (npm install -g react-native-cli) windows 只能搭建Android 开发环境 Mac 下既能搭建Android 环境&…

斥资4亿,收购这家WLAN厂商,结果……

晚上好&#xff0c;我的网工朋友 不少朋友可能有隐形&#xff0c;2019年的时候&#xff0c;Juniper花费4.05亿美元&#xff0c;收购WiFi初创公司Mist Systems。 Mist Systems是一家买无线产品起家的公司&#xff0c;由前思科高管创建的。主打的产品是“AI-Driven WLAN”&…

linux安装firefox

1.下载对应包 https://www.mozilla.org/en-US/firefox/all/#product-desktop-release 2. 挂载桌面链接(如果/usr/bin/firefox下有的话,先删除) ln -s /opt/firefox/firefox /usr/bin/firefox 3.执行以下命令&#xff0c;即可启动Firefox客户端&#xff1a; firefox

TCP协议报文

前言 TCP/IP协议簇——打开虚拟世界大门中&#xff0c;已经给大家大致介绍了TCP/IP协议簇的分层。 TCP (Transmission Control Protocol)传输控制协议&#xff0c;在TCP/IP协议簇中&#xff0c;处于传输层。是为了在不可靠的互联网络&#xff08;IP协议&#xff09;中&#x…

LangChain学习笔记;给老师的ChatGPT使用指南;中国大模型顶级闭门会交流笔记;飞桨开源任务挑战大赛 | ShowMeAI日报

&#x1f440;日报&周刊合集 | &#x1f3a1;生产力工具与行业应用大全 | &#x1f9e1; 点赞关注评论拜托啦&#xff01; &#x1f916; 飞桨PaddlePaddle开源任务挑战大赛&#xff0c;首届「开放原子开源大赛」等你参与 官网&#xff1a;https://competition.atomgit.com…