翻转字符串
344.反转字符串
题目链接:344. 反转字符串 - 力扣(LeetCode)
题目要求:编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 s 的形式给出。不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。
示例 1:
输入:s = ["h","e","l","l","o"]输出:["o","l","l","e","h"]
示例 2:
输入:s = ["H","a","n","n","a","h"]输出:["h","a","n","n","a","H"]
思路: 根据函数头可知输入的字符串已经是字符数组的形式了,所以只要使用双指针遍历数组,交换头尾对应位置元素位置,即可完成反转字符串的操作,相对来说较为简单
public static void reverseString(char[] s) {
int left = 0;
int right = s.length - 1;
while(left <= right ) {
char temp = s[left];
s[left] = s[right];
s[right] = temp;
left++;
right--;
}
541反转字符串II
题目链接:
题目要求:给定一个字符串 s 和一个整数 k,从字符串开头算起,每计数至 2k 个字符,就反转这 2k 字符中的前 k 个字符。如果剩余字符少于 k 个,则将剩余字符全部反转。如果剩余字符小于 2k但大于或等于 k 个,则反转前 k 个字符,其余字符保持原样。
示例 1:
输入:s = "abcdefg", k = 2
输出:"bacdfeg"
示例 2:
输入:s = "abcd", k = 2
输出:"bacd"
整体思路:字符串—>toCharArray()—>数组—>String.valueOf()—>字符串
方法一:双指针
定义两个指针,分别指向str[0]和str[k],翻转该段区间(左闭右闭)元素,完成后指针分别走2k步,此时两个指针中间区域即为第二个需要翻转的区域....;
对最末尾不足2k长度部分分情况讨论(此时尾指针已经越界):
如果长度小于k,则反转头指针到尾部的部分元素;如果长度大于k,此时k-2k部分已完成反转,无需特殊考虑
public static String reverseStr(String s, int k) {
String newStr = null;
char[] str = s.toCharArray(); // 字符串转换为数组
if(k >= str.length) { // 特殊情况考虑:步长大于数组长度的情况
// 算法和尾巴长度小于k一致,但是需要单独放在前面判断
int left = 0;
int right = str.length - 1;
while(left <= right ) { // 翻转字符串
char temp = str[left];
str[left] = str[right];
str[right] = temp;
left++;
right--;
}
newStr = String.valueOf(str); // 数组转换为字符串
return newStr;
}
// 普遍情况
int i = 0; // 定义头指针
int j = k - 1; // 定义尾指针,指向第k个值
while(i < str.length ) { // 头指针走出数组则循环结束
int left = i;
int right = j;
while(left < right ) {
char temp = str[left];
str[left] = str[right];
str[right] = temp;
left++;
right--;
}
i += 2*k;
j += 2*k;
if(j >= str.length) { // 如果尾指针已经越界,则剩余长度不足k
left = i;
right = str.length - 1;
while(left <= right ) {
char temp = str[left];
str[left] = str[right];
str[right] = temp;
left++;
right--;
}
break;
}
}
newStr = String.valueOf(str);
return newStr;
}
方法二:思路和方法一大致相同,区别在于细节上的优化(速度提升了不少,直接击败率100%)
1)使用for循环,让变量i的步长为2k,使用k+i代替了j
2)定义了一个方法min(),比较k+i和数组长度的大小,返回两者中较小的那一个,避免了分情况讨论的步骤
class Solution {
public String reverseStr(String s, int k) {
char[] str = s.toCharArray();
for(int i = 0; i < str.length; i += 2*k) {
reverse(str,i,min(i+k,str.length));
}
return String.valueOf(str);
}
private static char[] reverse(char[] s, int i, int min) {
int left = i;
int right = min - 1;
while(left <= right ) {
char temp = s[left];
s[left] = s[right];
s[right] = temp;
left++;
right--;
}
return s;
}
private static int min(int i, int length) {
if(i >= length) {
return length;
}
return i;
}
}
搜集到的其他很好的方法
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);
}
}