344. 反转字符串
-
题目描述:编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 s 的形式给出。
不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。
-
思路:双指针,把数组内的元素收尾对调即可,但是需要一个temp来存换之前的原始的字符。题目描述中O(1)空间算是提醒了自己。
class Solution {
public void reverseString(char[] s) {
int left = 0;
int right = s.length - 1;
//这里可以写<= 也可以写<。写<=,如果元素个数是奇数,那最后left和right会一起指向最中间的字符,又进行了一遍交换(其实没啥用)
//写<,元素个数为奇数时,就不会对中间的字符进行操作。为偶数个字符时也满足要求。
while(left <= right) {
char temp = s[left];
s[left] = s[right];
s[right] = temp;
left++;
right--;
}
}
}
541. 反转字符串Ⅱ
-
题目描述: 给定一个字符串 s 和一个整数 k,从字符串开头算起, 每计数至 2k 个字符,就反转这 2k 个字符中的前 k 个字符。
如果剩余字符少于 k 个,则将剩余字符全部反转。
如果剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符,其余字符保持原样。
示例:
输入: s = "abcdefg", k = 2 输出: "bacdfeg"
-
思路(不是,是碎碎念):见代码。这道题想了好久好久才转过弯来,估计以后还是要卡壳,用最简单傻瓜的语言做了注释,希望二刷的时候自己还能看得懂自己写的是啥。。。
class Solution {
public String reverseStr(String s, int k) {
char[] ch = s.toCharArray();
//循环间隔2k个
for(int i = 0; i < ch.length; i += 2*k) {
//如果第i个数后k个数在长度范围以内,那么就相当于余下的数在k到2k之间,此时反转前k个数,即翻转从第i个到第(i + k - 1)个数;然后跳出循环,去判断下一个2k
if(i + k - 1 <= ch.length - 1) {
reverse(ch, i, i + k - 1);
continue;
} else { //如果第i个数后不够k个数了,加上(i + k - 1)已经超出数组长度了,那么剩下的数就都要翻转,此时就从i到最后一个数都翻转;
reverse(ch, i, ch.length - 1);
}
}
return new String(ch);
}
//写一个翻转字符串的逻辑,同344.题
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;
}
}
}
剑指offer 05.替换空格
-
题目描述:请实现一个函数,把字符串 s 中的每个空格替换成"%20"。
示例 1:输入:s = "We are happy." 输出:"We%20are%20happy."
-
思路:见讲解链接 & 代码批注
-
双指针解法:具体思路在代码批注
class Solution {
public String replaceSpace(String s) {
//双指针法
//先判断s的长度是否为0及s内是否填充为空,如果是,直接返回s即可。
if(s == null || s.length() == 0) {
return s;
}
//创建一个新的str,遍历s,遇到空格之后,就在新的str中添加3-1=2个空格。
StringBuilder str = new StringBuilder();
for(int i = 0; i < s.length(); i++) {
if(s.charAt(i) == ' ') {
str.append(" "); // 注意:append里要用双引号,用单引号会报错
}
}
//如果str的长度为0,意味着s中没有空格,所以str也没有添加空格,直接返回s即可
if(str.length() == 0) {
return s;
}
//如果s中有空格:定义两个指针
//left指针此时指向原来的s中的最后一个字符位置处。
int left = s.length() - 1;
//扩充原来s的长度,加上str中空格的长度就行,此时s的长度是把空格替换成%20后所需的长度
s += str.toString();
//riight指针此时指向的是s扩充长度后的最后一个位置处。
int right = s.length() - 1;
//把当前的扩充后的s转换为为字符型数组
char[] chars = s.toCharArray();
//往新长度的数组chars里填充元素
//left要从后往前遍历每一个元素;遇到空格时,right就开始填充0/2/%
while(left >= 0) {
if(chars[left] == ' ') {
chars[right--] = '0';
chars[right--] = '2';
chars[right] = '%';
} else { //否则,right就填充和left一样的值
chars[right] = chars[left];
}
left--;
right--;
}
return new String(chars);
}
}
- 解法2:(感觉这个更简单,更好思考)不用数组,用一个新字符串对象str,复制s中的内容,如果s中的是空格,str中就append“%20”,如果不是空格,就append“s中的内容”
class Solution {
public String replaceSpace(String s) {
//先判断s需不需要走下面的逻辑,剪枝
if(s.length() == 0 || s == null) {
return s;
}
//直接新建一个对象,存最终字符串结果
StringBuilder str = new StringBuilder();
//遍历s中的每个字符
for(int i = 0; i < s.length(); i++) {
//如果s中的是空格,那就在新对象里添加%20
if(s.charAt(i) == ' ') {
str.append("%20");
} else { //如果不是空格,就添加s中的字符
str.append(s.charAt(i));
}
}
return str.toString();
}
}
151.反转字符串中的单词
-
题目描述:给定一个字符串,逐个翻转字符串中的每个单词。
示例 1:
输入: "the sky is blue" 输出: "blue is sky the"
示例 2:
输入: " hello world! " 输出: "world! hello" 解释: 输入字符串可以在前面或者后面包含多余的空格,但是反转后的字符不能包括。
示例 3:
输入: "a good example" 输出: "example good a" 解释: 如果两个单词间有多余的空格,将反转后单词间的空格减少到只含一个。
-
思路:"the sky is blue "
- 移除多余空格:“the sky is blue” (与27.移除元素的逻辑一样,双指针!)
- 将整个字符串反转:“eulb si yks eht”
- 将每个单词反转:“blue is sky the”
剑指offer58-Ⅱ. 左旋转字符串
-
题目描述:字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部。请定义一个函数实现字符串左旋转操作的功能。限制:1 <= k < s.length <= 10000
示例 1:输入: s = "abcdefg", k = 2 输出: "cdefgab"
示例 2:
输入: s = "lrloseumgh", k = 6 输出: "umghlrlose"
-
思路:局部反转 + 整体反转
具体步骤为:反转区间为前n的子串 反转区间为n到末尾的子串 反转整个字符串
class Solution {
public String reverseLeftWords(String s, int n) {
//先把String转换为StringBuilder可变字符串类
StringBuilder sb = new StringBuilder(s);
//把两个局部都先翻转
reverseString(sb, 0, n-1);
reverseString(sb, n, s.length() - 1);
//最后整体反转,再toString转换为String类
return sb.reverse().toString();
}
public void reverseString(StringBuilder sb, int left, int right) {
while(left < right) {
char temp = sb.charAt(left);
sb.setCharAt(left, sb.charAt(right));
sb.setCharAt(right, temp);
left++;
right--;
}
}
}