文章目录
day08学习内容
day08主要内容
- 反转字符串
- 反转字符串2
- 替换数字
- 翻转字符串里面的单词
- 右旋转字符串
一、 反转字符串
核心思路
1、很简单的一题,没啥好说的
2、记录一下异或的用法,第一次见
1.正确写法1
class Solution {
public 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--;
}
}
}
2.正确写法–使用异或
class Solution {
public void reverseString(char[] s) {
int l = 0;
int r = s.length - 1;
while (l < r) {
s[l] ^= s[r];
s[r] ^= s[l];
s[l] ^= s[r];
//等价于下面的写法
//s[l] = (char) (s[l]^ s[r]);
//s[r] = (char) (s[r]^s[l]);
//s[l] = (char) (s[l]^s[r]);
l++;
r--;
}
}
}
怎么理解上面的代码
- 初始化指针:
1.1.int l = 0;:左指针l指向数组的第一个字符。
1.2.int r = s.length - 1;:右指针r指向数组的最后一个字符。 - 循环条件:while (l < r) 确保左指针始终小于右指针。当这两个指针相遇或交错时,数组已经完全反转。
- 交换字符:
3.1. s[l] ^= s[r];:对s[l]和s[r]进行异或运算,并将结果存储在s[l]中。此时,s[l]存储了s[l]和s[r]的异或结果。
3.2. s[r] ^= s[l];:用s[l](现在包含s[l]和s[r]的异或结果)与s[r]进行异或运算,并将结果存储在s[r]中。此时,s[r]存储了原始的s[l]值。
3.3. s[l] ^= s[r];:再次用s[r](现在包含原始的s[l]值)与s[l]进行异或运算,并将结果存储在s[l]中。此时,s[l]存储了原始的s[r]值,从而完成了两个字符的交换。 - 移动指针:
4.1. l++;:左指针向右移动一位。
4.2. r–;:右指针向左移动一位。 - 重复:当左指针小于右指针时,重复上述交换和移动指针的步骤,直到整个数组被反转。
再来个demo
public class Example {
public static void main(String[] args) {
// 定义两个整数
int a = 5; // 二进制表示为 0101
int b = 10; // 二进制表示为 1010
// 对两个整数进行异或操作
int result = a ^ b;
// 输出结果
System.out.println("异或结果: " + result); // 输出 15,二进制表示为 1111
}
}
2.1. 这样写的好处是?
这个异或操作被用来在不使用临时变量的情况下交换两个字符。通过连续三次异或同一个值(在这种情况下是 s[r]),s[l] 的原始值会被恢复并存储在 s[r] 中,而 s[r] 的原始值则会被存储在 s[l] 中,从而完成了两个字符的交换。
这种方法避免了使用额外的内存空间来存储临时值
。
二、反转字符串2
思路
- 怎么每隔2K个元素计数一次
- 怎么反转这2k字符中的前 k个字符。
- 怎么判断剩余字符少于 k 个
- 怎么判断剩余字符小于 2k 但大于或等于 k 个
1.正确写法1
class Solution {
public String reverseStr(String s, int k) {
if (s.length() < 2) return s;
char[] c = s.toCharArray();
for (int i = 0; i < s.length(); i += 2*k) {
//这里说明剩余字符数小于k个。
if (i + k > s.length()) {
reverse(c, i, s.length() - 1);
break;
}
//反转前k个
reverse(c, i, i + k - 1);
}
return new String(c);
}
public void reverse(char[] ch, int start, int end) {
while (start < end) {
char t = ch[start];
ch[start] = ch[end];
ch[end] = t;
end--;
start++;
}
}
}
1.1.为什么i + k > s.length()表示剩余字符少于 k 个
很简单,这个条件i + k > s.length()意味着从索引i开始到字符串末尾的字符数不足k个。换句话说,如果我们尝试从索引i开始反转k个字符,我们将超出字符串的边界。因此,我们需要反转从索引i到字符串末尾的所有字符,并终止循环。
举个例子
假设s = “abcdefg"且k = 3。
当i = 0时,i + k = 0 + 3 = 3,小于或等于字符串长度,这里满足大于2K,所以只反转前K个,即我们会反转前3个字符(“abc”),得到"cbadefg”。
当i = 3时,i + k = 3 + 3 = 6,小于或等于字符串长度,因此我们会反转接下来的3个字符(“def”),得到"cbadfeg"。
当i = 6时,i + k = 6 + 3 = 9,大于字符串长度,因此我们知道只剩下1个字符(“g”),不足k个。此时,我们将反转从索引6到字符串末尾的所有字符(“g”),得到"cbadfeg",并且终止循环。
1.2.为什么i + k <= s.length()表示剩余字符少于 2k 个 但大于K个
和1.1反着来就对了
三、替换数字
略
四、翻转字符串里面的单词
1.思考
核心思路
- 先看懂题目,开头和结尾的空格需要删除,中间如果有多个空格,那么只保留一个空格。
- 先翻转全部单词,不管每个单词里面的顺序
- 然后翻转每个单词的字母顺序(所谓单词就是用空格隔开的就是单词)
- 复杂在于多余的空格删除 :双指针法删除多余空格
2.正确写法
不会写,抄的题解,后面想明白了再来补
五、右旋转字符串
卡码网的,先略过
总结
1.感想
- 翻转字符串用了异或法,体会一下和使用临时变量存储并替换的区别。主要好处就是节省内存空间。
- 翻转字符串里面的单词,这题对我来说比较难吧。。
- 明天要刷KMP了,又是全新的东西,加油吧
2.思维导图
本文思路引用自代码随想录,感谢代码随想录作者。