内容:
- 反转字符串(344)
- 反转字符串II(541)
- 替换空格(剑指offer 05)
- 翻转字符串里的单词(151)
- 左旋转字符串(剑指offer 58-II)
1.反转字符串
难度:🔥
1.1 思路分析
我们只需要两个指针指向char型数组的头和尾部,进行交换,然后两个指针同时向移动即可。
如图:
1.2 代码实现
class Solution {
public void reverseString(char[] s) {
for(int i = 0,j = s.length - 1;i < j;i++,j--) {
//char temp = s[i];
//s[i] = s[j];
//s[j] = temp;
s[i] ^= s[j];
s[j] ^= s[i];
s[i] ^= s[j];
}
}
}
1.3 收获总结
- 了解位运算符实现交换的方法
- 明白反转区间的定义是左闭右开还是左闭右闭
2.反转字符串II
难度:🔥🔥🔥
2.1 思路分析
我们首先得到String
类型对应的char
型数组,使用for
循环,每次遍历2*k
个元素,同时使用start
来记录开始反转的位置,end
来保存反转的结束位置,然后实现基本的反转。
2.2 代码实现
class Solution {
public String reverseStr(String s, int k) {
//得到该字符串对应的char型数组
char[] chars = s.toCharArray();
for(int i = 0;i < chars.length;i += 2 * k){
//start 为 开始反转的位置
int start = i;
//如果后面的数够k个,则反转前k(对应索引位置start + k - 1)个。不够则反转start到chars.length - 1
int end = Math.min(chars.length - 1,start + k - 1);
while(start < end){
chars[start] ^= chars[end];
chars[end] ^= chars[start];
chars[start] ^= chars[end];
start++;
end--;
}
}
//这里返回新的字符串
return new String(chars);
}
}
2.3 注意事项
- 问题的关键在于理解
int end = Math.min(chars.length - 1,start + k - 1)
3.替换空格
难度:🔥🔥
3.1 思路分析
通过StringBuilder
创建一个新的字符串可以很容易解决这个问题
3.2 代码实现
class Solution {
public String replaceSpace(String s) {
//使用append,简单方法
StringBuilder sb = new StringBuilder();
for(int i = 0;i < s.length();i++){
if (s.charAt(i) == ' '){
sb.append("%20");
}else{
sb.append(s.charAt(i));
}
}
return sb.toString();
}
}
3.3 收获总结
- 要熟悉
java
中String,StringBuilder,char
类型的使用与转换
4.翻转字符串里的单词
难度:🔥🔥🔥🔥
4.1 思路分析
这里要求不使用split
函数
这题考察的内容十分综合,是一道很好的题目
主要分为三步:
- 去除字符串中多余的空格,并且每个单词间只有一个空格
- 将整个字符串进行反转
- 将每个单词进行反转
4.2 代码实现
在实现过程中会遇到很多小问题,例如边界问题,
if
判断问题等等
class Solution {
//主要分为三步:
//1.去除字符串中多余的空格,并且每个单词间只有一个空格
//2.将整个字符串进行反转
//3.将每个单词进行反转
public String reverseWords(String s) {
StringBuilder s1 = removeExtraSpaces(s);
System.out.println(s1);
reverseString(s1,0,s1.length() - 1);
reverseEachWord(s1);
return s1.toString();
}
//双指针法实现去除字符串里面多余的空格并且让每个单词之间只有一个空格
// private StringBuilder removeExtraSpaces(String s){
// char[] ch = s.toCharArray();
// int slow = 0;
// for(int fast = 0;fast < s.length();fast++){
// //首先遍历到s字符串的第一个字符
// if (ch[fast] != ' '){
// if (slow != 0){
// ch[slow++] = ' ';
// }
// while(fast < s.length() && ch[fast] != ' '){
// ch[slow++] = ch[fast++];
// }
// }
// }
// StringBuilder sb = new StringBuilder();
// for(int i = 0;i < slow;i++){
// sb.append(ch[i]);
// }
// return sb;
// }
//使用StringBuilder
private StringBuilder removeExtraSpaces(String s){
int start = 0;
int end = s.length() - 1;
while(s.charAt(start) == ' '){start++;}
while(s.charAt(end) == ' '){end--;}
StringBuilder sb = new StringBuilder();
while(start <= end){
char c = s.charAt(start);
if(c != ' ' || sb.charAt(sb.length() - 1) != ' '){
sb.append(c);
}
start++;
}
return sb;
}
//对指定区间进行反转,左闭右闭
public void reverseString(StringBuilder sb, int start, int end) {
while (start < end) {
char temp = sb.charAt(start);
sb.setCharAt(start, sb.charAt(end));
sb.setCharAt(end, temp);
start++;
end--;
}
}
private void reverseEachWord(StringBuilder s){
//起始下标
int start = 0;
int end = 1;
while(start < s.length()){
while(end < s.length() && s.charAt(end) != ' '){
end++;
}
reverseString(s,start,end - 1);
start = end + 1;
end = start + 1;
}
}
}
4.3 收获总结
- 双指针法实现去除空格是比较困难的,使用
StringBuilder
和append
会更容易 - 对指定区间进行反转这种方法要熟练使用
- 去除空格中
if(c != ' ' || sb.charAt(sb.length() - 1) != ' ')
是判断当c
不为空格时我们添加c
,如果c
为空格则去判断我们的sb
字符串中最后一位是否为空格,如果不是,则将c(此时指向空格)
添加到sb
中,继续向后遍历
5.左旋转字符串
难度:🔥🔥
5.1 思路分析
这题主要考察反转指定区间字符串的使用
具体操作步骤:
- 反转区间为前n的子串
- 反转区间为n到末尾的子串
- 反转整个字符串
如图:
5.2 代码实现
class Solution {
public String reverseLeftWords(String s, int n) {
StringBuilder sb = new StringBuilder(s);
reserveString(sb,0,n - 1);
reserveString(sb,n,s.length() - 1);
reserveString(sb,0,sb.length() - 1);
return sb.toString();
}
private void reserveString(StringBuilder s,int start,int end){
while(start < end) {
char temp = s.charAt(start);
s.setCharAt(start,s.charAt(end));
s.setCharAt(end,temp);
start++;
end--;
}
}
}
5.3 收获总结
- 注意反转函数是否包含边界,从而正确处理要去反转的区间的边界