- 344.反转字符串
:::info
如果题目关键的部分直接用库函数就可以解决,建议不要使用库函数。
不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。 ::: 代码:(详细注释)
分析:void reverseString(vector<char>& s) {
for (int i = 0, j = s.size() - 1; i < s.size()/2; i++, j--) {
swap(s[i],s[j]);
}
}
swap可以有两种实现。
一种就是常见的交换数值:
int tmp = s[i];
s[i] = s[j];
s[j] = tmp;
一种就是通过位运算:
s[i] ^= s[j];
s[j] ^= s[i];
s[i] ^= s[j];
解释一下这里
关键:
- 两个相同的数异或的结果是 0,
- 一个数和 0 异或的结果是它本身
- 异或运算支持运算的交换律和结合律
所以:
有和
要让 (swap)
根据黄色可知
更多关于位运算
https://zhuanlan.zhihu.com/p/65968533
https://www.runoob.com/w3cnote/bit-operation.html
- 541.反转字符串Ⅱ
:::info
模拟题
当需要固定规律一段一段去处理字符串的时候,要想想在在for循环的表达式上做做文章。 ::: 代码:(详细注释)
:::info 注意这里的迭代器区间是默认的左闭右开、class Solution {
public:
string reverseStr(string s, int k) {
for (int i = 0; i < s.size(); i += (2 * k)) {
// 1. 每隔 2k 个字符的前 k 个字符进行反转
// 2. 剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符
if (i + k <= s.size()) {
reverse(s.begin() + i, s.begin() + i + k );
continue;
}
// 3. 剩余字符少于 k 个,则将剩余字符全部反转。
reverse(s.begin() + i, s.begin() + s.size());
}
return s;
}
};
体会reverse(s.begin() + i, s.begin() + i + k ); 刚好取到了[i,i+k)下标的元素,也就是从i数k个元素。 :::
分析:
实现reverse函数区间是左闭右闭区间
class Solution {
public:
void reverse(string& s, int start, int end) {
for (int i = start, j = end; i < j; i++, j--) {
swap(s[i], s[j]);
}
}
string reverseStr(string s, int k) {
for (int i = 0; i < s.size(); i += (2 * k)) {
// 1. 每隔 2k 个字符的前 k 个字符进行反转
// 2. 剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符
if (i + k <= s.size()) {
reverse(s, i, i + k - 1);
continue;
}
// 3. 剩余字符少于 k 个,则将剩余字符全部反转。
reverse(s, i, s.size() - 1);
}
return s;
}
};