代码随想录算法训练营第十三天(2)|541. 反转字符串II
文档讲解:代码随想录
难度:easy
附:冲
passion!!!passion!!!passion!!!
541. 反转字符串II
力扣题目链接(opens new window)
给定一个字符串 s 和一个整数 k,从字符串开头算起, 每计数至 2k 个字符,就反转这 2k 个字符中的前 k 个字符。
如果剩余字符少于 k 个,则将剩余字符全部反转。
如果剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符,其余字符保持原样。
示例:
输入: s = "abcdefg", k = 2
输出: "bacdfeg"
思路
方法1
- String是字符常量,由题目要求可知需要对其变化,即需要变量,而且是单线程操作为了效率使用StringBuffer
- 循环的判定条件:交换完成的指针位置是否在数组长度内
- 三目运算判断和k的关系:如果start+k>length,则剩余位置不够k,则返回length(之后将对剩余字符全部执行反转操作)反之返回start+k。
- 三目运算判断和2k的关系:如果start+2k>length,则剩余位置不够2k,则返回length(之后将反转前 k 个字符)其余字符保持原样反之返回start+2k。
- 对start和firstk之间的元素进行反转(substring() 方法确定范围)
- 判断是否在k到2k范围(如果不足k个元素firstk和secondkt均为length,如果够k,firstk为start+k,如果不够2k,secondk为length(length<start+k))
- 对secondkt和firstk之间的元素进行反转(同5)
- start+2k
- 返回res
class Solution {
public String reverseStr(String s, int k) {
StringBuffer res = new StringBuffer();
int length = s.length();
int start = 0;
while (start < length) {
// 找到k处和2k处
StringBuffer temp = new StringBuffer();
// 与length进行判断,如果大于length了,那就将其置为length
int firstK = (start + k > length) ? length : start + k;
int secondK = (start + (2 * k) > length) ? length : start + (2 * k);
//无论start所处位置,至少会反转一次
temp.append(s.substring(start, firstK));
res.append(temp.reverse());
// 如果firstK到secondK之间有元素,这些元素直接放入res里即可。
if (firstK < secondK) { //此时剩余长度一定大于k。
res.append(s.substring(firstK, secondK));
}
start += (2 * k);
}
return res.toString();
}
}
补充1:
1,String是字符串常量。
StringBuffer是字符串变量(线程安全)。
StringBuilder是字符串变量(线程不安全)。
2,对String新赋值时会改变其对象引用,同时会回收原对象,影响性能。
3,StringBuffer是对对象本身修改,不会产生垃圾。
4,少量字符串操作使用String,单线程内大量字符串操作使用StringBuilder,多线程内大量字符串操作使用StringBuffer;
5,速度StringBuilder>StringBuffer>String.
原文链接:https://blog.csdn.net/zhao4878179/article/details/125816084
补充2:
substring() 方法
用法:substring() 方法用于提取字符串中介于两个指定下标之间的字符。
语法:string.substring(start,stop)
示例:
let str = "0123456789"
str.substring(0) // 0123456789 输入0会原字符串输出
str.substring(3) // 3456789 从第三位开始截取,如果第二个参数忽略则截取到字符串末尾
str.substring(3,7) // 3456 前包括后不包括
提示:substring 不支持负数,如果是负数会输出原字符串原文链接:https://blog.csdn.net/qq_34402069/article/details/124758417
方法2
- tochararray()方法将字符串对象中的字符转换为字符数组
- 循环
- 判断尾数够不够k个来取决end指针的位置
- 交换
//题目的意思其实概括为 每隔2k个反转前k个,尾数不够k个时候全部反转
class Solution {
public String reverseStr(String s, int k) {
char[] ch = s.toCharArray();
for(int i = 0; i < ch.length; i += 2 * k){
int start = i;
//这里是判断尾数够不够k个来取决end指针的位置
int end = Math.min(ch.length - 1, start + k - 1);
//用异或运算反转
while(start < end){
ch[start] ^= ch[end];
ch[end] ^= ch[start];
ch[start] ^= ch[end];
start++;
end--;
}
}
return new String(ch);
}
}
// 还可以用temp来交换数值
class Solution {
public String reverseStr(String s, int k) {
char[] ch = s.toCharArray();
for(int i = 0;i < ch.length;i += 2 * k){
int start = i;
// 判断尾数够不够k个来取决end指针的位置
int end = Math.min(ch.length - 1,start + k - 1);
while(start < end){
char temp = ch[start];
ch[start] = ch[end];
ch[end] = temp;
start++;
end--;
}
}
return new String(ch);
}
}
补充3:
tochararray()可以将字符串对象中的字符转换为字符数组。也可以将字符串视为char型数组。
Split和ToCharArray的区别:
(1)split是根据你需要按照的分隔符来分割的。
比如:String a = "avc,d,e,s,f"; String []b = a.split(',');这个就是根据逗号将数据分开,遍历输出得到的b的对象为"avc","d","e","s","f"。
(2)toCharArray是将String对象的每一个下标位的对象保存在char[]中。
比如:String a = "abcd"; char[] b = a.toCharArray();这个b保存的信息就是['a','b','c','d']。
方法3
- 每隔 2k 个字符的前 k 个字符进行反转
- 剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符
- 剩余字符少于 k 个,则将剩余字符全部反转
// 解法3
class Solution {
public String reverseStr(String s, int k) {
char[] ch = s.toCharArray();
// 1. 每隔 2k 个字符的前 k 个字符进行反转
for (int i = 0; i< ch.length; i += 2 * k) {
// 2. 剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符
if (i + k <= ch.length) {
reverse(ch, i, i + k -1);
continue;
}
// 3. 剩余字符少于 k 个,则将剩余字符全部反转
reverse(ch, i, ch.length - 1);
}
return new String(ch);
}
// 定义翻转函数
public void reverse(char[] ch, int i, int j) {
for (; i < j; i++, j--) {
char temp = ch[i];
ch[i] = ch[j];
ch[j] = temp;
}
}
}