1.题目描述
给定一个字符串 s 和一个整数 k,从字符串开头算起,每计数至 2k 个字符,就反转这 2k 字符中的前 k 个字符。
- 如果剩余字符少于 k 个,则将剩余字符全部反转。
- 如果剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符,其余字符保持原样。
示例1:
输入:s = “abcdefg”, k = 2
输出:“bacdfeg”
示例2:
输入:s = “abcd”, k = 2
输出:“bacd”
示例3:
输入:s = “a”, k = 2
输出:“a”
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/reverse-string-ii
2.题目分析
本题要求我们对每2k个字符就进行前半部分的倒置,这看起来似乎是一个繁琐的循环,其实我们不必想的那么复杂,完全可以通过在循环遍历中每次i前进2k步
进行解决。所以我们的循环写法是for(int i=0;i<len;i+=2*k)
,这时我们的外层循环就只是进行每次要倒置的子串的位置定位,至于子串的倒置我们还是跟往常一样通过双向双指针进行解决。
基本思路就是上面所讲的那样,对于不同长度最后的结尾部分字串的操作是不一样的。按照题目要求,假设最后一次循环因为i+2k>=len
会跳出,那么在之前一次还未跳出的状态中,分为以下两种情况:
- 剩下的部分长度
小于k
,也就是说i+k>len-1
,此时我们就要将全部的剩下的元素进行倒置,所以我们呢将双指针设为left=i,right=len-1;
- 剩下的部分长度
大于k
,也就是i+k<len
,此时剩下的部分是足够进行一次倒置的,所以我们还是跟i
没到尾部一样设left=i,right=i+k-1;
3.题目解答
3.1 朴素模拟法
class Solution {
public:
string reverseStr(string s, int k) {
//初始化返回字符串、保存长度
string s1 =s;
int len=s1.size();
//一次遍历循环,i每次前进2k步
for(int i=0;i<len;i+=2*k){
//交换局部字串操作
int left,right;
//待交换部分长度大于k
if(len-i>k){
left=i,right=i+k-1;
}else{
//最后的待交换部分长度小于k
left=i,right=len-1;
}
//子串倒置
while(left<right){
swap(s1[right],s1[left]);
left++;
right--;
}
}
return s1;
}
};
3.2 使用库函数reverse
————————更快更强
string reverseStr(string s, int k) {
int n = s.length();
for (int i = 0; i < n; i += 2 * k) {
reverse(s.begin() + i, s.begin() + min(i + k, n));
}
return s;
}
总结:字符串操作跟数组的操作、vector的操作是基本相同的