文章目录
344.反转字符串
- 标签:字符串
- 难度:4.0
跟反转数组没区别。
提供了两种方法,区别在于交换的实现。
方法一:临时变量(常用)
public void reverseString(char[] s) {
char temp;
int left = 0;
int right = s.length - 1;
while(right > left){
temp = s[left];
s[left++] = s[right];
s[right--] = temp;
}
}
方法二:位运算(了解)
public void reverseString(char[] s) {
int left = 0;
int right = s.length - 1;
while (right > left) {
s[left] ^= s[right]; //构造 a ^ b 的结果,并放在 a 中
s[right] ^= s[left]; //将 a ^ b 这一结果再 ^ b ,存入b中,此时 b = a, a = a ^ b
s[left++] ^= s[right--]; //a ^ b 的结果再 ^ a ,存入 a 中,此时 b = a, a = b 完成交换
}
}
541.反转字符串II
- 标签:字符串
- 难度:5.0
相比上一道题,这道明显麻烦了点,但基本思想还是手动模拟,没有什么巧解。
public String reverseStr(String s, int k) {
// 这步很重要,把字符串转为字符数组,在java里更好处理
char[] s1 = s.toCharArray();
// 一开始把左右指针定在前k个元素
int left = 0;
int right = k-1;
// 如果一共都没有k个元素,把右指针调整到最后一个元素处
if(right >= s1.length){
right = s1.length - 1;
}
// 外层循环:每2k个元素循环一次
while(true){
// 因为左右指针在交换过程中会动,所以要用临时变量保存起来
int tempLeft = left;
int tempRight = right;
// 和上道题一样的交换过程
while(left < right) {
char temp;
temp = s1[right];
s1[right--] = s1[left];
s1[left++] = temp;
}
// 改变左右指针的位置到下一个区间
left = tempLeft + 2*k;
right = tempRight + 2*k;
// 左指针都超了,说明不需要再交换了
if(left > s1.length) break;
// 如果左指针没超,右指针超了,说明剩下不到k个元素,就把右指针调到最后一个元素处
if(right > s1.length){
right = s1.length - 1;
}
}
// 别忘了恢复成字符串,String类的构造函数可以直接传入字符数组!
return new String(s1);
}
剑指Offer 05.替换空格
- 标签:字符串
- 难度:5.0
借助Java的StringBuilder类直接开辟新的数组,这个题可以说是非常之简单。
但还是要重点关注一下双指针解法,可以在原数组(字符串)上扩容,而不用开新数组。具体是数有多少空格,将原数组扩容空格个数的2倍,然后快指针从后往前遍历原数组,慢指针在后面按顺序填坑。快指针遇到空格,慢指针依次填入“0”、“2”、“%”;快指针遇到非空格元素,慢指针就填这个元素。
所以和27.移除元素很像!
方法一:StringBuilder
//使用一个新的对象,复制 str,复制的过程对其判断,是空格则替换,否则直接复制,类似于数组复制
public static String replaceSpace(String s) {
if (s == null) {
return null;
}
//选用 StringBuilder 单线程使用,比较快,选不选都行
StringBuilder sb = new StringBuilder();
//使用 sb 逐个复制 s ,碰到空格则替换,否则直接复制
for (int i = 0; i < s.length(); i++) {
//s.charAt(i) 为 char 类型,为了比较需要将其转为和 " " 相同的字符串类型
//if (" ".equals(String.valueOf(s.charAt(i)))){}
if (s.charAt(i) == ' ') {
sb.append("%20");
} else {
sb.append(s.charAt(i));
}
}
return sb.toString();
}
方法二:双指针(重要)
public String replaceSpace(String s) {
if(s == null || s.length() == 0){
return s;
}
//扩充的空间=空格数量2倍
StringBuilder str = new StringBuilder();
for (int i = 0; i < s.length(); i++) {
if(s.charAt(i) == ' '){
str.append(" ");
}
}
//若是没有空格直接返回
if(str.length() == 0){
return s;
}
//有空格情况 定义两个指针
int left = s.length() - 1;//左指针:指向原始字符串最后一个位置
s += str.toString();
int right = s.length()-1;//右指针:指向扩展字符串的最后一个位置
char[] chars = s.toCharArray();
while(left>=0){
if(chars[left] == ' '){
chars[right--] = '0';
chars[right--] = '2';
chars[right] = '%';
}else{
chars[right] = chars[left];
}
left--;
right--;
}
return new String(chars);
}
这个题还要注意健壮性,一个是数组为空或者为null,另一个容易遗忘,就是遍历完了发现原字符串里没有空格,这样要直接返回原字符串。
151.翻转字符串里的单词
- 标签:字符串、双指针
- 难度:6.5
这个题很精彩,解法比较多,也比较复杂。
关注后续更新。
剑指Offer 58-II.左旋转字符串
- 标签:字符串、双指针
- 难度:5.0
很巧妙的思想,精华就三行代码,不多说了。
public String reverseLeftWords(String s, int n) {
// 精华在此↓↓↓
s = reverse(s,0,n-1);
s = reverse(s,n,s.length()-1);
s = reverse(s,0,s.length()-1);
return s;
}
// 和上面第一题一样的反转操作
public String reverse(String s, int left, int right){
char[] s1 = s.toCharArray();
while(left < right){
char temp;
temp = s1[left];
s1[left++] = s1[right];
s1[right--] = temp;
}
return new String(s1);
}