目录
344.反转字符串
题目链接:344. 反转字符串
思路
利用双指针,分别从头、尾开始,相互交换位置。
代码实现
class Solution {
public:
void reverseString(vector<char>& s) {
for(int left = 0, right = s.size()-1; left < right; ++left, --right){
char tmp = s[left];
s[left] = s[right];
s[right] = tmp;
}
}
};
541. 反转字符串II
题目链接:541. 反转字符串 II
思路
先将前k个字符反转,然后跳过k个字符,重复上述操作;
代码实现
class Solution {
public:
string reverseStr(string s, int k) {
int size = s.size();
int curr = 0;
while(curr < size){
if(k == 1) break;
// 反转前k个字符
int right;
if(curr + k - 1 < size) right = curr + k - 1;
else right = size - 1;
for(int left = curr; left < right; ++left, --right){
swap(s[left], s[right]);
}
// 跳过k个字符
curr += 2 * k;
}
return s;
}
};
小结
这里反转字符可以使用库函数reverse,要学会使用库函数。
LCR 122. 路径加密
呃呃本来是剑指Offer的,但是力扣题目下架了,换题!题目简单了好多,原题是:剑指Offer 05.替换空格
题目链接:LCR 122. 路径加密
代码实现
class Solution {
public:
string pathEncryption(string path) {
for(int i = 0; i < path.size(); ++i){
if(path[i] == '.') path[i] = ' ';
}
return path;
}
};
剑指Offer 05.替换空格
这一题没做,但是看到了解析,感觉又是很巧妙,先判断有多少个空格,预留出足够的位置,再利用双指针从后往前填充字符串。
151.翻转字符串里的单词
题目链接:151. 反转字符串中的单词
思路与代码实现
这题我的思路是,先把每个单词的首字母位置记录下来,然后再从后向前将各个单词录入新字符串中。不过这种算法的内存使用有点高
class Solution {
public:
string reverseWords(string s) {
int size = s.size();
// 记录各单词首字母的位置
stack<int> init;
init.push(0);
for(int i = 1; i < size; ++i){
if(s[i - 1] == ' ' && s[i] != ' ') init.push(i);
}
// 从后往前录入新字符串
string result;
while(!init.empty()){
for(int i = init.top(); s[i] != ' ' && i < size; ++i){
result = result + s[i];
}
init.pop();
result += ' ';
}
while(result[result.size()-1] == ' ')
result.erase(result.end() - 1);
return result;
}
};
不要使用辅助空间,空间复杂度要求为O(1)。
要求空间以后,就有点难了,解析上的思路却很巧,先将整个字符串反转,再将哥哥单词反转,这样就成了今天前两道题的结合;值得注意的是,去除多余空格时,考虑到时间复杂度的问题,可采用双指针的方法,而不是erase。
class Solution {
public:
string reverseWords(string s) {
int size = s.size();
// 利用双指针除去多余空格
int slow = 0;
for(int fast = 0; fast < size; ++fast){
if(s[fast] != ' '){
if(slow > 0) s[slow++] = ' ';
while(s[fast] != ' ' && fast < size) s[slow++] = s[fast++];
}
}
s.resize(slow);
size = slow;
// 整体反转
reverse(s.begin(), s.end());
// 各个单词反转
slow = 0;
for(int fast = 0; fast <= size; ++fast){
if(fast == size || s[fast] == ' '){
reverse(s.begin() + slow, s.begin() + fast);
slow = fast + 1;
}
}
return s;
}
};
小结
实现反转,无从下手,可以试试看是不是局部反转和整体反转的结合而成;去除多余空格,可以和27.移除元素相联系起来。
剑指Offer58-II.左旋转字符串
题目链接:LCR 182. 动态口令(力扣题目下架了,这题题意相同)
思路
为了让本题更有意义,提升一下本题难度:不能申请额外空间,只能在本串上操作。
根据上一题的思路,这一题也试试局部反转加整体反转:
首先将所得结果整体反转,得到的是前target个字符局部反转,其后字符局部反转;所以反推,原字符串前target个字符反转,后面也反转,再整体反转就能得到最终结果。
代码实现
class Solution {
public:
string dynamicPassword(string password, int target) {
// 先反转前target个字符
reverse(password.begin(), password.begin() + target);
// 再反转其后字符
reverse(password.begin() + target, password.end());
// 再整体反转
reverse(password.begin(), password.end());
return password;
}
};