突破编程_C++_字符串算法(检查一个字符串是否是某个字符串的旋转)

1 算法题 :检查一个字符串是否是某个字符串的旋转

1.1 题目含义

检查一个字符串是否是某个字符串的旋转,这是一个常见的字符串操作问题。具体来说,这个问题要求判断给定的一个字符串是否可以通过将另一个字符串的所有字符按照相同的顺序进行循环位移(即旋转)来得到。

例如,字符串 “abcde” 是 “cdeab” 的旋转,因为可以将 “cdeab” 向左旋转两个位置得到 “abcde”。但是,字符串 “abc” 并不是 “bcd” 的旋转,因为即使尝试所有可能的旋转方式,也无法得到 “abc”。

1.2 示例

示例 1:

  • 输入:s1 = “abcde”, s2 = “cdeab”
  • 输出:true
  • 解释:字符串 “cdeab” 可以通过向左旋转两个位置得到字符串 “abcde”。

示例 2:

  • 输入:s1 = “abc”, s2 = “bcd”
  • 输出:false
  • 解释:无法通过旋转字符串 “bcd” 来得到字符串 “abc”。

示例 3:

  • 输入:s1 = “waterbottle”, s2 = “erbottlewat”
  • 输出:true
  • 解释:字符串 “erbottlewat” 可以通过向右旋转一定位置得到字符串 “waterbottle”。

2 解题思路

解题思路如下:

(1)判断长度:
首先,检查两个字符串 s1 和 s2 的长度是否相等。如果长度不等,那么 s2 显然不能是 s1 的旋转,因为旋转操作不会改变字符串的长度。直接返回 false。

(2)拼接字符串:
将 s1 和 s1 拼接在一起,形成一个新的字符串 doubleS1。如果 s2 是 s1 的旋转,那么 s2 必然是 doubleS1 的子串。

(3)查找子串:
使用双指针在 doubleS1 中查找 s2。遍历 doubleS1,每次检查从当前位置开始的子串是否与 s2 相等。这可以通过逐个字符比较来实现。

(4)返回结果:
如果在 doubleS1 中找到了与 s2 相等的子串,说明 s2 是 s1 的旋转,返回 true。
如果遍历完整个 doubleS1 都没有找到匹配的子串,则返回 false。

这个解题思路的时间复杂度是 O(n),其中 n 是字符串 s1(或 s2)的长度,因为我们最多需要遍历 doubleS1 一次。空间复杂度是 O(n),因为需要存储拼接后的字符串 doubleS1。虽然这个空间复杂度不是最优的,但这种方法实现起来比较简单,并且对于大多数情况来说性能也是可接受的。如果需要进一步优化空间复杂度,可以考虑不使用额外的空间存储拼接后的字符串,但这通常会增加代码的复杂性。

3 算法实现代码

3.1 使用拼接遍历

如下为算法实现代码:

#include <iostream>  
#include <string>  class Solution
{
public:bool isRotation(const std::string& s1, const std::string& s2){// 检查两个字符串长度是否相等  if (s1.length() != s2.length()) {return false;}// 判断空字符串  if (s1.length() == 0) {return true;}// 拼接字符串  std::string doubleS1 = s1 + s1;// 使用双指针查找子串  size_t s2Len = s2.length();for (size_t i = 0; i < doubleS1.length() - s2Len + 1; ++i) {if (doubleS1.substr(i, s2Len) == s2) {// 找到匹配的子串,返回true  return true;}}// 没有找到匹配的子串,返回false  return false;}
};

这段代码定义了一个 isRotation 函数,它接受两个字符串 s1 和 s2 作为参数,并返回一个布尔值,表示 s2 是否是 s1 的旋转。

注意,此代码使用了 std::string 类的 substr 成员函数来从 doubleS1 中提取与 s2 长度相同的子串,并检查它们是否相等。这种方法简单直观,但可能不是最高效的,特别是当字符串很长时。在实际应用中,可能需要根据性能要求进行优化。

调用上面的算法,并得到输出:

int main() 
{Solution s;// 示例1  std::string s1 = "abcde";std::string s2 = "cdeab";std::cout << "Is " << s2 << " a rotation of " << s1 << "? " << (s.isRotation(s1, s2) ? "Yes" : "No") << std::endl;// 示例2  s1 = "abc";s2 = "bcd";std::cout << "Is " << s2 << " a rotation of " << s1 << "? " << (s.isRotation(s1, s2) ? "Yes" : "No") << std::endl;// 示例3  s1 = "waterbottle";s2 = "erbottlewat";std::cout << "Is " << s2 << " a rotation of " << s1 << "? " << (s.isRotation(s1, s2) ? "Yes" : "No") << std::endl;return 0;
}

上面代码的输出为:

Is cdeab a rotation of abcde? Yes
Is bcd a rotation of abc? No
Is erbottlewat a rotation of waterbottle? Yes

3.2 使用数组循环

上面算法的实现,使用到了字符串拼接,占用了一定的内存空间,如果避免使用拼接字符串的方法,可以将 s1 视为一个循环数组,然后检查 s2 是否可以通过将 s1 的某个起始位置作为起点,按照数组顺序读取得到。如果找到了这样的起始位置,那么 s2 就是 s1 的旋转。

如下为算法实现代码:

#include <iostream>  
#include <string>  
#include <vector>  class Solution
{
public:bool isRotation(const std::string& s1, const std::string& s2){// 检查两个字符串长度是否相等  if (s1.length() != s2.length()) {return false;}// 判断空字符串  if (s1.length() == 0) {return true;}int n = s1.size();for (int i = 0; i < n; ++i) {bool isMatch = true;for (int j = 0; j < n; ++j) {int index = (i + j) % n; // 循环数组的索引  if (s1[index] != s2[j]) {isMatch = false;break;}}if (isMatch) {return true; // 找到匹配的起始位置  }}return false; // 没有找到匹配的起始位置  }
};

在这个实现中,使用了两个嵌套的循环。外部循环遍历 s1 的所有可能的起始位置,内部循环则用于比较从当前起始位置开始的 s1 的子串和 s2 是否相同。内部循环使用取模运算 (i + j) % n 来实现循环数组的索引,这样就可以模拟从 s1 的不同位置开始读取字符的过程。

如果对于某个起始位置i,s1 的子串和 s2 完全相同,那么就找到了匹配的起始位置,并返回 true。如果遍历完所有可能的起始位置都没有找到匹配,那么返回 false。

这种方法的时间复杂度是 O(n^2),其中 n 是字符串的长度,因为代码中有两层循环。虽然这种方法避免了拼接字符串,但它在处理长字符串时可能不够高效。对于更高效的解决方案,可以考虑使用哈希表或其他数据结构来加速字符匹配的过程。

4 测试用例

以下是针对上面算法的测试用例,基本覆盖了各种情况:

(1)基础测试用例:

  • 输入1:s1 = “abcde”
  • 输入2:s2 = “cdeab”
  • 预期输出:true(s2 是 s1 的旋转,因为 s1 可以通过将末尾的"de"移到开头得到 s2)

(2)完全相同字符串:

  • 输入1:s1 = “abcde”
  • 输入2:s2 = “abcde”
  • 预期输出:true(相同的字符串可以视为自己的旋转)

(3)长度不同字符串:

  • 输入1:s1 = “abcde”
  • 输入2:s2 = “abcdef”
  • 预期输出:false(s2 不是 s1 的旋转,因为它们的长度不同)

(4)旋转一个字符:

  • 输入1:s1 = “a”
  • 输入2:s2 = “a”
  • 预期输出:true(一个字符的旋转是其自身)

(5)非旋转字符串:

  • 输入1:s1 = “hello”
  • 输入2:s2 = “olleh”
  • 预期输出:false(s2 不是 s1 的旋转,因为即使移动 s1 的字符也无法得到 s2)

(6)包含重复字符的字符串:

  • 输入1:s1 = “abbacaa”
  • 输入2:s2 = “bacaaab”
  • 预期输出:true(尽管 s1 和 s2 都包含重复字符,但 s2 仍然是 s1 的旋转)

(7)空字符串:

  • 输入1:s1 = “”
  • 输入2:s2 = “”
  • 预期输出:true(空字符串是自身的旋转)

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

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

相关文章

SpringBoot 线程池异步调用

yml配置文件 # 线程池 threadPool:# 核心线程池大小corePoolSize: 2# 最大线程数maxPoolSize: 5# 缓冲队列大小queueCapacity: 200# 允许线程空闲时间&#xff08;单位&#xff1a;默认为秒&#xff09;keepAliveSeconds: 10# 允许线程等待时长&#xff08;单位&#xff1a;默…

vue3中el-input输入无效的原因之一

表单的model用的是&#xff1a;reactive let updateForm reactive({ id: 0, className: "" }); reactive的数据不能这么赋值&#xff0c;会破坏响应性 错误方法&#xff08;&#xff09;{ updateForm { id: 0, className: "asdasdas" }; } 解决方法&…

Qt + mqtt对接阿里云平台(二)

一、MQTT协议 1、MQTT相关概念 MQTT&#xff08;Message Queuing Telemetry Transport&#xff0c;消息队列遥测传输协议&#xff09;&#xff0c;是一种基于发布/订阅&#xff08;publish/subscribe&#xff09;模式的"轻量级"通讯协议&#xff0c;该协议构建于TC…

移动目标检测的几种常用方法和代码实现

移动目标检测的几种常用方法和代码实现 帧差法&#xff08;Frame Difference Method&#xff09;持续帧差法&#xff08;Continuous Frame Difference Method&#xff09;总结背景减法自适应背景减法总结 帧差法和持续帧差法都是通过分析视频帧之间的差异来检测场景中的运动对象…

1.5如何缓解图像分类任务中训练数据不足带来的问题?

1.5 图像数据不足时的处理方法 场景描述 在机器学习中&#xff0c;绝大部分模型都需要大量的数据进行训练和学习(包括有监督学习和无监督学习)&#xff0c;然而在实际应用中经常会遇到训练数据不足的问题。 比如图像分类&#xff0c;作为计算机视觉最基本的任务之一&#xff0…

生成 Linux/ubuntu/Debian 上已安装软件包的列表

你可以在终端中使用以下命令生成已安装软件包的列表&#xff1a; 列出所有已安装的软件包&#xff1a; dpkg --get-selections要将列表保存到文件中&#xff1a; dpkg -l > installed_packages_detailed.txt这将在当前目录中创建一个名为“installed_packages_detailed.txt”…

高效提升控制效率 | 基于ACM32 MCU的LED灯箱控制器方案

LED灯箱上各种文字、图案有序跳跃、交替辉映&#xff0c;产生强烈的视觉冲击力&#xff0c;被广泛应用于商场、美容美发、宾馆、娱乐场所等地方。 锁存器的工作原理 在LED和数码管显示方面&#xff0c;要维持一个数据的显示&#xff0c;往往要持续的快速的刷新。尤其是在四段八…

Python算法100例-3.6 自守数

1.问题描述2.问题分析3.算法设计4.求给定数的位数5.分离给定数中的最后几位6.确定程序框架7.完整的程序 1&#xff0e;问题描述 自守数是指一个数的平方的尾数等于该数自身的自然数。例如&#xff0c; 5 2 25 &#xff0c; 2 5 2 625 &#xff0c; 7 6 2 5776 &#xff0c…

java基础-锁之volatilesynchronized

文章目录 volatilevolatile内存语义volatile的可见性volatile无法保证原子性volatile禁止重排优化硬件层的内存屏障volatile内存语义的实现下面是基于保守策略的JMM内存屏障插入策略。下面是保守策略下&#xff0c;volatile写插入内存屏障后生成的指令序列示意图下图是在保守策…

Mac下java环境搭建

JDK 教程:MAC安装JDK及环境变量配置-CSDN博客 建议JDK7和JDK8都装上,因为一些老项目是用JDK7开发,使用JDK8编译时报错。(若没有老项目,直接安装jdk8) 若配置环境变量时找不到JDK的安装路径,有两种方式: 方式一、mac默认位置为:/Library/Java/JavaVirtualMachines/…

Android APP性能指标(二)

文章目录 一、响应时间1.1 数据获取1.2 响应时间指标测试点1.3 启动速度测试点1.4 响应时间测试解决方法 二、流量2.1 数据获取2.2 流量测试关注点2.3 测试标准 三、电量3.1 连接手机3.2 数据获取3.3 获取APP的UID3.3 重置电池数据收集数据3.4 电量指标测试 四、温度五、性能测…

打包系统待优化点

Base.Widget.AppCompat.ActivityChooserView中相关资源重复 D:\channelPackage\ToolConfigPath\games\dcpPro\100081\mumu\tempRes\values\attrs.xml:1171: error: duplicate value for resource attr/displayOptions with config . D:\channelPackage\ToolConfigPath\games\d…

linux系统nginx常用命令

查nginx位置 find / -name nginx nginx目录&#xff1a;/usr/local/ 查看nginx进程号 ps -ef |grep nginx 停止进程 kill 2072 启动 ./sbin/nginx /usr/local/nginx/sbin/nginx -t -c /usr/local/nginx/conf/nginx.conf 启动并校验校验配置文件 ./sbin/nginx -t 看到如下显…

【C++精简版回顾】19.异常处理

1.throw抛出问题 int print(int a,int b) {if (b 0)throw b;return a / b; } 2.try与catch解决问题 try {print(2, 0); } catch (int b) {cout << "竟然是&#xff1a;"<<b<<endl; } 结果&#xff1a; 补充1&#xff1a;可以抛出字符串等 1.throw…

day13_微服务监控Nginx(微服务集成SBA)

文章目录 1 微服务系统监控1.1 监控系统的意义1.2 SBA监控方案1.3 SBA实战1.3.1 创建SBA服务端1.3.2 微服务集成SBA 1.4 微服务集成logback1.5 配置邮件告警 2 Nginx2.1 Nginx简介2.2 下载和安装2.2.1 方式1&#xff1a;window本地安装2.2.1.1 下载2.2.1.2 安装2.2.1.3 目录结构…

关于 typeof 与 instanceof 区别引出的原型对象问题

一、关于 typeof 与 instanceof 区别&#xff1a; typeof 和 instanceof 是 JavaScript 中用于检查变量类型的两个不同操作符&#xff0c;它们在使用上有着明显的区别和不同的适用场景。 typeof typeof 是一个一元操作符&#xff0c;用于返回一个变量或表达式的数据类型的字符…

Docker部署的MySQL容器数据备份与导入

适用场景 采用Docker部署MySQL时&#xff0c;需要对MySQL的数据&#xff0c;通过服务器命令的方式进行导入导出的情况。 假设MySQL容器名为dsms_mysql5.7&#xff0c;用户名为root&#xff0c;密码为123456&#xff0c;数据库名为demo&#xff0c;备份SQL文件为backup.sql&am…

简单认识算法

什么是算法&#xff1f; 解决某个实际问题的过程和方法。 排序算法 1.冒泡排序 打印结果&#xff1a; 2.选择排序 打印结果&#xff1a; 优化选择排序&#xff1a;因为每一轮都需要以当前位置为基准与后面元素比较&#xff0c;太过繁琐&#xff0c;所以可以找到后面元素中较小…

Long使用==

1、背景&#xff1a;测试程序的时候发生了没数据的bug,于是在sevice层的一堆代码中调试&#xff0c;最后发现问题是在stream的filter方法中对两个Long使用造成的问题。 2、测试代码&#xff1a; Long a Long.valueOf(340);Long b Long.valueOf(340);System.out.println(a b)…

指针的学习4

目录 回调函数 qsort使用样例 使用qsort函数排序整形数据 使用qsort函数排序结构体 回调函数 回调函数就是一个通过函数指针调用的函数。如果把函数的指针&#xff08;地址&#xff09;作为参数传递给另一个函数&#xff0c;当这个指针被用来调用其所指向的函数时&#xf…