部分反转字符串,
1.先将字符串整体反转(局部字符串的位置是对的了,字符串中的字符顺序不是反的了)
2. 然后再局部反转就可以实现 (将局部字符串反转为正常的字符串)
344.反转字符串
反转字符串中的单词,将右边的几个字符放到字符串的左边都可以这么操作
class Solution {
public:
void reverseString(vector<char>& s) {
int left = 0;
int right = s.size() -1;
//双指针交换,思路有了很简单
while(left < right) {
swap(s[left],s[right]);
left ++;
right --;
}
}
};
//代码简化
class Solution {
public:
void reverseString(vector<char>& s) {
for (int i = 0, j = s.size() - 1; i < s.size()/2; i++, j--) {
swap(s[i],s[j]);
}
}
};
541. 反转字符串II
建议:本题又进阶了,自己先去独立做一做,然后在看题解,对代码技巧会有很深的体会。
题目链接/文章讲解/视频讲解
注意自定义反转字符串的区间定义
class Solution {
public:
// 注意:这里是左闭右闭区间,因为是数组下标,所以end需要减1
string reverseStr(string& s, int start, int end) {
for(int i = start , j = end - 1 ; i < j; i ++, j--) {
swap(s[i],s[j]);
}
return s;
}
string reverseStr(string s, int k) {
int temp_size = 0;
int i = 0;
for(int i = 0; i < s.size(); i += (2*k)) {
if(s.size() >= i + k ){
// 注意:这里是左闭右闭区间
s = reverseStr(s, i, i + k);
} else {
//剩余小于k,将剩余全部反转
s = reverseStr(s, i, s.size());
}
}
return s;
}
};
//使用C++ reverse 函数
class Solution {
public:
string reverseStr(string s, int k) {
int temp_size = 0;
int i = 0;
for(int i = 0; i < s.size(); i += (2*k)) {
if(s.size() >= i + k ){
// 注意:这里是左闭右闭区间
reverse(s.begin() + i, s.begin() + i + k);
} else {
//剩余小于k,将剩余全部反转
reverse(s.begin() + i, s.end());
}
}
return s;
}
};
卡码网:54.替换数字
建议:对于线性数据结构,填充或者删除,后序处理会高效的多。好好体会一下。
题目链接/文章讲解
#include <iostream>
using namespace std;
#include <string>
string replace_number(string& str, string& replace_str) {
int count = 0;
int old_size = str.size();
for(int i = 0; i < str.size(); i ++) {
if(str[i] >= '0' && str[i] <= '9') {
count ++;
}
}
//被替换的字符也占一个位置,所以这里要-1
str.resize(str.size() + (replace_str.length() - 1) * count);
for(int i = old_size - 1, j = str.size() - 1; i >= 0;){
if(str[i] < '0' || str[i] > '9') {
str[j --] = str[i --];
} else {
//反向将替换字符串替换
for(int t = replace_str.size() - 1; t >= 0; t --) {
str[j--] = replace_str[t];
}
i--;// 替换的那个字符对应的原字符所以i--
}
}
return str;
}
int main() {
string str = "123abc123ab123";
string replace_str = "number";
cout << str << endl;
replace_number(str, replace_str);
cout << str << endl;
string replace_str1 = "AA";
string str1 = "123abc123ab123";
replace_number(str1, replace_str1);
cout << str1 << endl;
return 0;
}
151.翻转字符串里的单词
建议:这道题目基本把 刚刚做过的字符串操作 都覆盖了,不过就算知道解题思路,本题代码并不容易写,要多练一练。
class Solution {
public:
string delete_empty(string& s) {
int count = 0;
int slow = 0;
int fast = 0;
while(s.size() > 0 && s[fast] == ' '&& fast < s.size()){
fast ++;
}
for(; fast < s.size() ;) {
//如果是个字符,直接加入进来,
// 如果是个空格,空格后必须是个字符,这个空格才保留,这样末尾就不会有空格
if(s[fast] != ' ' || (s[fast] == ' ' && fast + 1 < s.size() && s[fast + 1] != ' ')) {
s[slow ++] = s[fast++];
} else {
fast ++;
}
}
//slow 是下标是从0开始的,所以这里resize为slow
s.resize(slow);
return s;
}
string reverseWords(string s) {
delete_empty(s);
reverse(s.begin(),s.end() );
int slow = 0;
//因为 reverse 库的区间是[) 所以 这里需要遍历到 == size()(s.end()) 才能将最后的单词反转
for(int i = 0; i <= s.size(); i ++) {
// 这里的i == s.size() 必须写在前面,s[i] 获取有可能越界
if(i == s.size() || s[i] == ' ') {
reverse(s.begin() + slow, s.begin() + i);
slow = i + 1;
}
}
return s;
}
};
//使用临时字符串辅助从后往前的双指针法的代码
string reverseMessage1(string message) {
if(message.empty()) {
return "";
}
string result = "";
int left = message.size() - 1;
int length = 0;
cout << left << endl;
for(; left >= 0; left --) {
cout << left << endl;
cout << "message[left]" << message[left] << endl;
if(message[left] != ' ') {
length ++;
} else {
if(length != 0) {
//这里在注意要left要+1 ,因为此时left上的字符为空格,需要取他后边的
result.append(message.substr(left + 1, length));
result.push_back(' ');
length = 0;
}
}
}
//如果length != 0 说明原字符串中第一个字符不是空格,所以需要将原数据的第一段数据添加进来
if(length != 0) {
result.append(message.substr(left + 1, length));
}
//如果result的最后一个字符是空格需要去掉
if(!result.empty() && result.back() == ' ') {
result.pop_back();
}
return result;
}
卡码网:55.右旋转字符串
建议:题解中的解法如果没接触过的话,应该会想不到
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
string right_recerse(string &str, int num) {
//先整体反转
reverse(str.begin(), str.end());
//局部反转
//反转变前边的原后边的部分
reverse(str.begin(), str.begin() + num);
//反转原前面的部分
reverse(str.begin() + num,str.end());
return str;
}
int main() {
string str = "12345abc";
cout << str << endl;
cout << right_recerse(str,3) << endl;
}