题目描述:给定一个字符串 s 和一个整数 k,从字符串开头算起,每计数至 2k 个字符,就反转这 2k 字符中的前 k 个字符。
如果剩余字符少于 k 个,则将剩余字符全部反转。 如果剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符,其余字符保持原样。
示例 1:
输入:s = "abcdefg", k = 2 输出:"bacdfeg"
示例 2:
输入:s = "abcd", k = 2 输出:"bacd"
提示:
1 <= s.length <= 104 s 仅由小写英文组成 1 <= k <= 104
方法解析:模拟法
按照题目的要求,一步一步进行求解: 1、使用subString在字符串s上依次截取子字符串subStr,长度为2k,对于长度不满2k的有多少截取多少; 2、对截取的字符串进行相关操作: 如果 subStr >= k: 把subStr的前k个字符进行逆置; 如果 subStr < k:把把子字符串完全逆置;
代码实现:
public static String reverseStr(String s, int k){
String ans = "";
for(int i = 0; i < s.length(); i += 2*k){ // i的处理结果为每次添加2*k
String subStr = s.substring(i, Math.min(s.length(), i + 2*k)); // 获取每次需要处理放的子串
ans += reverseHalfStr(subStr, k);
}
return ans;
}
// 如果 s.length() >= k 则逆置字符串s的前k个字符,返回完全逆置字符串s
public static String reverseHalfStr(String s, int k){
String answerStr = "";
if(s.length() < k){ // 如果字符串的长度小于k则逆置整个字符串s
answerStr = swap(s); // 逆置字符串s
}else{ // 如果字符串的长度大于等于k,则逆置字符串s的前k个字符
String subStr = s.substring(0, k); // 获取字符串的一般
answerStr = swap(subStr); // 逆置字符串subStr
}
// 如果s.length < k则逆置整个字符串s并进行返回,若s.lenth >= k则逆置字符串s的前k个字符并进行返回
return s.length() < k ? answerStr : answerStr + s.substring(k);
}
// 返回逆置字符串s
public static String swap(String s){
if(s.length() == 0 || s == null){
return null;
}
char[] chars = s.toCharArray();
for (int i = 0; i < chars.length/2; i++) {
// 交换函数
chars[i] ^= chars[chars.length - i -1];
chars[chars.length - i -1] ^= chars[i];
chars[i] ^= chars[chars.length - i -1];
}
return String.valueOf(chars);
}
官方代码:
官方代码和上述思想也是同样的道理,也是进行模拟处理,其最精髓的地方在于先把字符串转化为字符数组,然后遍历字符数组,
这里变量i的每次进行i += 2k操作;然后在字符数组上进行相关的逆置操作。
public static String reverseStr1(String s, int k){
int n = s.length();
char[] chars = s.toCharArray();
for(int i = 0; i < n; i += 2*k){
reverse(chars, i, Math.min(i+k, n) -1); // 一段一段的对字符数组进行逆置,精髓所在
}
return new String(chars);
}
// 对字符数组chars中的[left, right]区域进行逆置,而不是把整个字符数组进行逆置,使用双指针的精髓所在
public static void reverse(char[] chars, int left, int right){
while (left < right){
char temp = chars[left];
chars[left] = chars[right];
chars[right] = temp;
left++;
right--;
}
}
总结:
1、Java字符串求子串函数subString(startIndex, endIndex)要特别注意startIndex,endIndex为下标,并且从0开始,子字符串的范围为前闭后开区间[startIndex, endIndex);
2、平常使用for循环时,变量i经常为i++或者i +=2,这里使用的是 i+= 2*k, 把字符串分成n段, 每段长为2k;
3、官方进行逆置操作时候使用了双指针left和right,可以在字符数组中随机逆置[left,right]区间的字符,而不是逆置整个字符数组,这是很厉害的地方,要学会这种逆置方式;
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/reverse-string-ii



