LC 344.反转字符串
题目链接:LC 344.反转字符串
思路:前提是不使用额外的空间。因此也是用双指针法,从开头l和结尾r开始遍历,交换指针对应的值。终止条件为l>=r(当为偶数个时,遍历到最后l>r;当为奇数个时,遍历到最后l==r结束)。
代码:
class Solution {
public:
void reverseString(vector<char>& s) {
int l = 0;
int r = s.size() - 1;
while(l<r){
char temp = s[l];
s[l] = s[r];
s[r] = temp;
//以上三句可简化为
// swap(s[l], s[r]);
++l;
--r;
}
}
};
LC 541. 反转字符串II
题目链接:LC 541. 反转字符串II
思路:遍历的时候每次走2k步,然后每次反转2k中的前k个。重点是最后剩余的字符数目少于K,与大于等于K时的区别,可以在每次迭代时进行判断。
代码:
class Solution {
public:
string reverseStr(string s, int k) {
if(s.size()<=1)return s;
for(int i=0; i<s.size(); i+=2*k){
if(i+k<=s.size()){//实际时i+k-1<=s.size()-1,都看得下标值
reverse(s.begin()+i, s.begin()+(i+k));//C++自带的函数,输入是字符串的地址,且不是对输入的最后字符进行反转,而是其前一个s.begin()+(i+k)-1
}
else{
reverse(s.begin()+i, s.end());
}
}
return s;
}
};
剑指Offer 05.替换空格
题目链接:剑指Offer 05.替换空格
思路:
思路1:可以创建一个新的vector,遍历字符串,若遇到空格就将其变为‘%20‘插入vector中,若不为空格则将该值插入vector中。
思路2:为了不占用额外得空间,可以先遍历字符串找到空格的个数,然后延长字符串长度。双指针,一个指向就字符串末尾,一个指向新串末尾,从后向前遍历,若为空格就插入’%20‘,否则直接插入该值。
代码:
class Solution {
public:
//思路1
// string replaceSpace(string s) {
// string temp;
// for(char i : s){
// if(i==' ')temp+="%20";
// else temp+=i;
// }
// return temp;
// }
//思路2
string replaceSpace(string s) {
int num = 0;
for(char i : s){
if(i==' ')++num;
}
if(num==0)return s;
int l = s.size() - 1;//保存旧长度
s.resize(s.size() + 2*num);//1变3(加2)
int r = s.size() - 1;
while(r!=l){
if(s[l]!=' ')s[r] = s[l];
else{
s[r] = '0';
--r;
s[r] = '2';
--r;
s[r] = '%';
}
--r;
--l;
}
return s;
}
};
LC 151.翻转字符串里的单词
题目链接:LC 151.翻转字符串里的单词
思路:分成三步,1先删除多余的空格;2反转整个字符串;3按空格反转单词
代码:
class Solution {
public:
//删除多余空格
void removeExtraSpace(string &s){
int num = 0;//统计删除多余空格后的字符转长度
for(int i=0; i<s.size(); i++){
//删除每个单词前面的空格
if(s[i]!=' '){//可删除最前面的空格,找到不为空格的char
//找单词末尾(下一个空格)
while(i<s.size() && s[i]!=' '){
s[num] = s[i];
++num;
++i;
}
//若有空格或者到最后,则手动加空格(在单词末尾加上空格)
s[num] = ' ';//不让s[num] = s[i],是因为s[i]可能溢出,这样每个单词后面都会有一个空格,返回时需要把最后一个空格删除
num++;
}
}
s.resize(num-1);//把最后的空格删除
}
string reverseWords(string s){
//1删除多余空格
removeExtraSpace(s);
//2反转整个字符串
reverse(s.begin(), s.end());
//3每个单词进行反转
int l = 0;
for(int r=0; r<s.size(); r++){
//若找到空格则反转开始到空格这段字符串
//r指向单词的末尾后的空格,l指向单词的第一个字母
if(s[r]==' '){
reverse(s.begin()+l, s.begin()+r);
l = r+1;
}
else if(r == s.size()-1){//到末尾时全部反转
reverse(s.begin()+l, s.end());
}
}
return s;
}
};
剑指Offer58-II.左旋转字符串
题目链接:剑指Offer58-II.左旋转字符串
思路:先反转局部再反转全局;或者先反转全局再反转局部,两者等价。先反转前k个字符组成的字符串和从k到最后的字符串,再反转全部字符串。
代码:
class Solution {
public:
//先局部再全局
string reverseLeftWords(string s, int n) {
//先反转前n个
reverse(s.begin(), s.begin()+n);//旋转从0到n-1的字符串
reverse(s.begin()+n, s.end());
reverse(s.begin(), s.end());
return s;
}
};
------------------------------------额外题目---------------------------------
(以上为训练营每日任务,本部分为自己刷题进度)
LC 226.翻转二叉树
题目链接:LC 226.翻转二叉树
思路:翻转改的是地址而不是值。可以深度遍历或者层次遍历若左右子树不全为空,就将左右子树翻转。
代码
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
//深度遍历-先序遍历-递归
//1 确定传入参数和返回参数类型
TreeNode* invertTree(TreeNode* root) {
//2 确定返回条件(终止条件)
if(root == nullptr)return root;
//3 单层递归逻辑
//先反转,再到左右子树(先序遍历)
swap(root->right, root->left);
invertTree(root->right);
invertTree(root->left);
return(root);
}
};