344.反转字符串
题目链接:344.反转字符串
一眼双 丁真 指针
class Solution {
public:
void reverseString(vector<char>& s) {
int left = 0, right = s.size() - 1;
while (left < right) {//当s为奇数时,直接跳过。当s为偶数时,交换后自动满足
s[left++] ^= s[right--] ^= s[left] ^= s[right];//交换。此方法仅限于整数,char在底层也算整数
}
}
};
因为^=操作符是right to left,所以最后执行的left和right上有自增自减
class Solution {
template <class T>
void fun(T& a, T& b) {
T tmp;
tmp = a;
a = b;
b = tmp;
}
public:
void reverseString(vector<char>& s) {
int left = 0, right = s.size() - 1;
while (left < right) {
fun(s[left++], s[right--]);
}
}
};
仿照算法std::reverse()函数写的
class Solution {
public:
//仿照算法reverse函数写的
void reverseString(vector<char>& s) {
int fisrt = 0, last = s.size();
while ((fisrt != last) && (fisrt != --last)) {
swap(s[fisrt++], s[last]);
}
}
};
541. 反转字符串II
题目链接:541. 反转字符串II
仔细读题,虽然leetcode表述也有歧义。
class Solution {
public:
string reverseStr(string s, int k) {
for (int idx = 0; idx < s.size(); idx += 2 * k/*每2k个判断一次*/) {
(idx + k < s.size())//剩余字符是否有k个
//reverse函数区间为左闭右开
? reverse(s.begin() + idx, s.begin() + idx + k)//有,结尾为 + k
: reverse(s.begin() + idx, s.end());//没有就直接到end
}
return s;
}
};
reverse函数参数是迭代器形式。
revese(s.begin(), s.end()),由end()定义为容器最后一位的下一位可知,reverse为左闭右开。
可以通过修改for循环计数语句,来修改遍历形式。i += 2 * k,视为将 2 * k 为一个单元。
替换空格
题目链接:已被Leetcode删除
用双指针。只需要在原来的字符串(内存上)修改。从后往前遍历时间复杂度就为
O
(
n
)
O(n)
O(n),从前往后为
O
(
n
2
)
O(n^2)
O(n2),因为填充一次后,还要整体移动后续字符。
其实很多数组填充类的问题,都可以先预先给数组扩容带填充后的大小,然后在从后向前进行操作。
class Solution {
public:
string replaceSpace(string s) {
int cnt = 0;//计算空格次数
for (auto& i : s) {
if (i == ' ') {
cnt++;
}
}
s.resize(s.size() + cnt * 2);//扩容
//slow指向原来数组长度结尾,fast指向新数组的结尾。
int slow = s.size() - 1 - 2 * cnt, fast = s.size() - 1;//从后往遍历
while (slow < fast) {//当两指针相遇,表示没有空格了,直接跳过就行。
if (s[slow] != ' ') {
s[fast--] = s[slow--];//原来赋给新的,都往前移一位
} else {
slow--;
s[fast--] = '0';
s[fast--] = '2';
s[fast--] = '%';
}
}
return s;
}
};
151.翻转字符串里的单词
题目链接: 151.翻转字符串里的单词
- step 1. 去除空格:
" wo he "->"wo he" - step 2. 反转整体 :
"wo he"->"eh ow" - step 3. 反转单词 :
"eh ow"->"he wo"
整体代码如下:
class Solution {
void removeSpace(string& par) {
int newIdx = 0;
for (int oldIdx = 0; oldIdx < par.size(); ++oldIdx) {
if (par[oldIdx] != ' ') {//跳过空格
if (newIdx != 0) {//非第一个单词
par[newIdx++] = ' ';//每个单词前都加空格
}
while (oldIdx < par.size()/*因为在下一行代码中,oldIdx++,所以要判断一下*/ && par[oldIdx] != ' ') {
par[newIdx++] = par[oldIdx++];
}
}
}
par.resize(newIdx);//因为循环最后一步为newIdx++,所以不是resize(newIdx + 1)
}
void reverseString(string& par, int left, int right) {
while (left < right) {
par[left++] ^= par[right--] ^= par[left] ^= par[right];
}
}
public:
string reverseWords(string s) {
removeSpace(s);
reverseString(s, 0, s.size() - 1);
int start = 0;//用来修改每个单词的翻转
for (int idx = 0; idx <=/*等于是为了让最后一个单词也满足翻转的区间*/ s.size(); ++idx) {
if (s[idx] == ' ' || idx == s.size()/*最后一个单词*/) {
reverseString(s, start, idx - 1);
start = idx + 1;//更新起点
}
}
return s;
}
};
剑指Offer58-II.左旋转字符串
题目链接:剑指Offer58-II.左旋转字符串
一眼字符串拼接。结果说反转。太离谱了。
class Solution {
public:
string reverseLeftWords(string s, int n) {
//字符串拼接
/* string tmp;
for (int i = n; i < s.size(); ++i) {
tmp += s[i];
}
for (int i = 0; i < n; i++) {
tmp += s[i];
}
return tmp;*/
//三个反转
reverse(s.begin(), s.begin() + n);//反转前n个
reverse(s.begin(), s.end());//全反转
reverse(s.begin(), s.end() - n);//反转前end - n个
return s;
}
};
文章介绍了多个关于字符串反转的编程问题解决方案,包括344.反转字符串、541.反转字符串II、剑指Offer05.替换空格、151.翻转字符串里的单词以及剑指Offer58-II.左旋转字符串。解题策略涉及双指针、位运算和字符串拼接及反转等技巧。

199

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



