344. 反转字符串
题目来源:344. 反转字符串 - 力扣(LeetCode)
文章来源:代码随想录
这道题用首尾双指针就行,个人代码如下:
class Solution {
public:
void reverseString(vector<char>& s) {
//定义left和right指针
int left = 0,right = s.size()-1;
char temp;
while(left<right){
temp = s[left];
s[left] = s[right];
s[right] = temp;
left++;right--;
}
return;
}
};
这道题还有一个原地交换的操作
s[i] ^= s[j];
s[j] ^= s[i];
s[i] ^= s[j];
这个原地操作的原理我去问deepseek,它的回答如下:
这段代码通过三次异或(XOR)操作实现了元素交换,其核心原理基于异或运算的三个关键性质:
自反性:
a ^ a = 0(任何数与自身异或结果为0)。恒等性:
a ^ 0 = a(任何数与0异或结果不变)。交换律与结合律:异或操作顺序不影响结果。
分步解析(假设初始时
s[i] = a,s[j] = b):
第一步:
s[i] ^= s[j]
等价于s[i] = a ^ b。此时s[i]存储了a和b的异或结果,而s[j]仍为b。第二步:
s[j] ^= s[i]
等价于s[j] = b ^ (a ^ b)。根据交换律和自反性,这简化为a(因为b ^ b = 0,0 ^ a = a)。此时s[j]变为a,s[i]仍为a ^ b。第三步:
s[i] ^= s[j]
等价于s[i] = (a ^ b) ^ a。同样利用交换律和自反性,这简化为b(a ^ a = 0,0 ^ b = b)。此时s[i]变为b,s[j]为a,完成交换。
541. 反转字符串II
题目链接:541. 反转字符串 II - 力扣(LeetCode)
这道题是模拟,直接实现即可,个人代码如下:
class Solution {
public:
string reverseStr(string s, int k) {
//定义反转那一段的起点和终点下标
int begin = 0,end,length = s.length(),i,j;
//如果这一整段能够替换,正常设置end
if(begin+k-1<length){
end = begin+k-1;
}
//如果不够一整段替换,设置end为字符串末尾
else{
end = length-1;
}
//当反转下标为最后一个元素也不用反转了
while(begin<length-1){
//开始进行替换操作
i = begin;
j = end;
while(i<j){
s[i] ^= s[j];
s[j] ^= s[i];
s[i] ^= s[j];
i++;j--;
}
//替换完之后要更新begin,end
if(begin+2*k<length-1){
begin += 2*k;
}
else{
break;
}
if(begin+k-1<length){
end = begin+k-1;
}
//如果不够一整段替换,设置end为字符串末尾
else{
end = length-1;
}
}
return s;
}
};
54.替换数字
题目链接:54. 替换数字(第八期模拟笔试)
参考文章:替换数字 | 代码随想录
图片来源于参考文章。
这道题直观来讲我是开辟额外数组来完成的。空间复杂度为O(n)时间复杂度为O(n),个人代码如下:
#include <bits/stdc++.h>
using namespace std;
int main(){
string str_a,str_b;
int i;
getline(cin,str_a);
//开始遍历,放入str_b中
for(i = 0;i<str_a.length();i++){
//如果是小写字母,就直接赋值给str_b
if(str_a[i]>='a'&&str_a[i]<='z'){
str_b.push_back(str_a[i]);
}
else{
str_b += "number";
}
}
for(int j = 0;j<str_b.length();j++){
cout<<str_b[j];
}
return 0;
}
但卡哥给出了空间复杂度更低的做法的原理和图解,卡哥文章已经写得很详细了,我这里就不再赘述。我只想强调文章的一个结论。
其实很多数组填充类的问题,其做法都是先预先给数组扩容到填充后的大小,然后再从后向前进行操作。
这么做有两个好处:
- 不用申请新数组。
- 从后向前填充元素,避免了从前向后填充元素时,每次添加元素都要将添加元素之后的所有元素向后移动的问题。
卡哥参考代码如下:
#include <iostream>
using namespace std;
int main() {
string s;
while (cin >> s) {
int sOldIndex = s.size() - 1;
int count = 0; // 统计数字的个数
for (int i = 0; i < s.size(); i++) {
if (s[i] >= '0' && s[i] <= '9') {
count++;
}
}
// 扩充字符串s的大小,也就是将每个数字替换成"number"之后的大小
s.resize(s.size() + count * 5);
int sNewIndex = s.size() - 1;
// 从后往前将数字替换为"number"
while (sOldIndex >= 0) {
if (s[sOldIndex] >= '0' && s[sOldIndex] <= '9') {
s[sNewIndex--] = 'r';
s[sNewIndex--] = 'e';
s[sNewIndex--] = 'b';
s[sNewIndex--] = 'm';
s[sNewIndex--] = 'u';
s[sNewIndex--] = 'n';
} else {
s[sNewIndex--] = s[sOldIndex];
}
sOldIndex--;
}
cout << s << endl;
}
}
763

被折叠的 条评论
为什么被折叠?



