55. 右旋字符串
题目描述
字符串的右旋转操作是把字符串尾部的若干个字符转移到字符串的前面。给定一个字符串 s 和一个正整数 k,请编写一个函数,将字符串中的后面 k 个字符移到字符串的前面,实现字符串的右旋转操作。
例如,对于输入字符串 “abcdefg” 和整数 2,函数应该将其转换为 “fgabcde”。
输入描述
输出描述
输入示例
2
abcdefg
输出示例
fgabcde
提示信息
暴力
程序首先通过 cin 读取用户输入的旋转位数 n 和字符串 s。然后,它通过两个循环构造右旋转后的字符串 a:
-
第一个循环从字符串 s 中取出最后 n 个字符,这是因为右旋转操作的定义是将字符串尾部的若干字符移到字符串的前面。
-
第二个循环取出字符串 s 开头到指定位置 s.size() - n 的字符,即除去被旋转到前面的那部分字符。
最后,程序输出构造好的字符串 a 并结束。
// 包含C++的全局库,包含了大部分常用的C++库。
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n; // 定义一个整数n,用来存储用户输入的旋转位数。
string s, a; // 定义两个字符串,s用来接收用户输入的原始字符串,a用来存储旋转后的字符串。
cin >> n >> s; // 从标准输入读取旋转位数和需要旋转的字符串。
// 遍历并添加字符串s尾部的n个字符到字符串a。
for(int i = s.size() - n; i < s.size(); i++)
a += s[i];
// 遍历并添加字符串s除去尾部n个字符的剩余部分到字符串a。
for(int i = 0; i < s.size() - n; i++)
a += s[i];
// 输出旋转后的字符串a。
cout << a << endl;
// 程序正常结束返回0。
return 0;
}
优化:不能申请额外空间,只能在本串上操作
思路
不能使用额外空间的话,模拟在本串操作要实现右旋转字符串的功能还是有点困难的。
那么我们可以想一下上一题目 151. 反转字符串中的单词 中讲过,
本题中,我们需要将字符串右移n位,字符串相当于分成了两个部分,如果n为2,符串相当于分成了两个部分,如图: (length为字符串长度)
右移n位, 就是将第二段放在前面,第一段放在后面,先不考虑里面字符的顺序,是不是整体倒叙不就行了。如图:
此时第一段和第二段的顺序是我们想要的,但里面的字符位置被我们倒叙,那么此时我们在把 第一段和第二段里面的字符再倒叙一把,这样字符顺序不就正确了。 如果:
其实,思路就是 通过 整体倒叙,把两段子串顺序颠倒,两个段子串里的的字符在倒叙一把,负负得正,这样就不影响子串里面字符的顺序了。
代码
这个程序利用了反转操作(reverse 函数)的性质来实现字符串的右旋转。这种方法的核心在于:
-
反转整个字符串:将整个字符串 s 反转后,原来在尾部的k个字符现在会移到字符串的前面。
-
反转字符串的前 n 个字符:这将刚才移到前面的 n 个字符再次反转回它们原来的顺序。
-
反转字符串的剩余部分:将前 n 个字符之后的部分再次反转,这样这部分字符也回到了它们原来的顺序。
通过上述步骤,字符串的后 n 个字符被移动到了字符串的前面,实现了字符串的右旋转操作。
// 包含了大部分常用的C++库,简化了头文件的包含过程。
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n; // 定义一个整数n,用来存储用户输入的旋转位数。
string s; // 定义一个字符串s,用来接收用户输入的原始字符串。
cin >> n >> s; // 从标准输入读取旋转位数和需要旋转的字符串。
// 第一步:反转整个字符串。
reverse(s.begin(), s.end());
// 第二步:反转字符串的前n个字符(现在这部分字符位于字符串的开头)。
reverse(s.begin(), s.begin() + n);
// 第三步:反转字符串的剩余部分,即从第n个字符到字符串的末尾。
reverse(s.begin() + n, s.end());
// 输出旋转后的字符串。
cout << s << endl;
// 程序正常结束返回0。
return 0;
}