题目分析
给定一个字符串 s
和一个正整数 k
,任务是将字符串 s
中的最后 k
个字符移动到字符串的前面,这种操作称为字符串的右旋转。例如,输入字符串 "abcdefg"
和整数 2
应得到 "fgabcde"
。
解题思路
为了实现右旋转操作,可以采用三次反转(reverse)策略。这种方法不仅直观,而且效率高,特别适用于在不额外使用过多空间的情况下处理字符串的问题。
步骤细化
-
反转整个字符串:
- 首先,对整个字符串进行反转。例如,对
"abcdefg"
反转后得到"gfedcba"
。
- 首先,对整个字符串进行反转。例如,对
-
反转前
k
个字符:- 然后,反转反转后字符串的前
k
个字符。对于k = 2
,将"gf"
反转成"fg"
。此时字符串变为"fgedcba"
。
- 然后,反转反转后字符串的前
-
反转剩余的字符:
- 最后,反转剩下的字符,即从索引
k
到字符串末尾的部分。对于上面的例子,将"edcba"
反转成"abcde"
。现在,整个字符串变为"fgabcde"
。
- 最后,反转剩下的字符,即从索引
代码解析
输入与初始化
#include <iostream>
#include <algorithm>
using namespace std;
string s;
int k;
int main(){
cin >> k >> s;
- 输入
k
和字符串s
,其中k
是需要旋转的字符数。
反转操作
reverse(s.begin(), s.end());
reverse(s.begin(), s.begin() + k);
reverse(s.begin() + k, s.end());
reverse(s.begin(), s.end())
:反转整个字符串。reverse(s.begin(), s.begin() + k)
:反转前k
个字符。reverse(s.begin() + k, s.end())
:反转从第k
个字符到字符串末尾的部分。
输出结果
cout << s;
return 0;
}
- 输出经过旋转后的字符串
s
。
示例
假设输入是 2
和 "abcdefg"
,输出将是 "fgabcde"
。
复杂度分析
- 时间复杂度:
O(n)
,其中n
是字符串的长度。每个字符在整个过程中只被访问和移动常数次。 - 空间复杂度:
O(1)
,在原字符串上就地进行操作,不需要额外的空间。
注意事项
- 需要考虑
k
大于字符串长度的情况。可以通过取模运算处理这种情况,即k = k % s.size()
,以避免不必要的完整旋转,这将使k
处于有效范围内。 - 考虑到字符串长度可能小于或等于
1
,在这种情况下,任何旋转都不会改变字符串的内容。