反转字符串的进阶练习:
题目分析:
给定一个字符串 s
和一个整数 k
,从字符串开头算起,每计数至 2k
个字符,就反转这 2k
字符中的前 k
个字符。
- 如果剩余字符少于
k
个,则将剩余字符全部反转。 - 如果剩余字符小于
2k
但大于或等于k
个,则反转前k
个字符,其余字符保持原样。
思路:
首先对于这题重要的一点是如何判断哪一个区域是需要反转的,因为实际上整个字符串是每2*k个进行一次反转,如果剩下的不够2*k个但大于k个则反转剩下的,这样就想到——利用for循环,i+=2*k,然后再判断每个2*k区间内的字符串的长度,来判断该怎么反转
那判断如何反转,就需要分析清楚一共有几种情况:
1. 当区间的长度=该段字符串的长度时,从开始到k-1(下标)反转
2. 当区间的长度>该段字符串的长度时,这里存在两种情况:
1)该段字符串长度<k,则所有都反转
2)该段字符串长度>k,则跟第一种情况一样,都是从开始到k-1反转字符
举个例子:
abcdefgh,k=3;
对于这个,先判断abcdef,然后它等于2k,则abc反转一下
——cbadefgh
然后从f往后就剩下gh,长度小于k,则直接反转
——cbadefhg
代码怎么写呢?
——首先这个字符串的长度l=8,k=3,i刚开始=0
1. 先判断l-i这段区域, 这段区域的字符>2k,可以在i到i+2*k里反转,那就把i到i+k-1的反转了
2.然后i+=2*k,再判断剩下的l-i是否大于k,
这里是小于k,就直接从i到l-1反转
3.如果再加一个字母ij的话,就从i到i+k-1反转,
4.如果再加几个字母变成abcdefghijklmn,则这时候判断>2k,则继续同1.来反转前k个字符
自己分析一下例子,是不是发现,可以利用l-i与k判断来实现反转的区分呢?那下面写代码就好写了。
代码:
char* reverseStr(char* s, int k) {
int i=0;
int l=strlen(s);//求长度
int p;
int q;
for(;i<l;i+=2*k)
{
// 1. 每隔 2k 个字符的前 k 个字符进行反转
// 2. 剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符
// 3. 剩余字符少于 k 个,则将剩余字符全部反转。
if(l-i>=k)
{
p=i;
q=i+k-1;
}else
{
p=i;
q=l-1;
}
while(p<q){
char t=s[p];
s[p++]=s[q];
s[q--]=t;
}
}
return s;
}
C++利用反转函数来写程序:
class Solution {
public:
string reverseStr(string s, int k) {
for (int i = 0; i < s.size(); i += (2 * k)) {
if (i + k <= s.size())
{
reverse(s.begin() + i, s.begin() + i + k );
} else
{
reverse(s.begin() + i, s.end());
}
}
return s;
}
};
总结:
1. 对于c语言中的l,需要求字符串长度,使用strlen即可,不要用sizeof,否则会报错
2.注意,这种题目中带着每这个字眼的,需要想到利用for循环,然后举个例子,来判断不同情况下所需要的代码块
3.注意在while循环中别忘了要让两个“指针”移动——++和--,否则会导致无限循环,出错。
4.在for循环中i要加2k,注意这里的2k不能直接这样写,要写成2*k,否则会报错——如下:
Char 16: error: fixed-point types not supported for this target [solution.c]
5.其实在c语言中的if可以改写为一行代码:
k = i + k > len ? len - i : k;
通过变换k来实现,不过这个没有if语句好想起来。
6.注意p和q“这两个充当指针的变量”,不是i+k,也不是l,而是l-1和i+k-1,数组下标记住是0开始的,所以这两个变量也要在本来的后面-1才是对的,不然可能运行对了,但是不通过。