344.反转字符串
介绍
编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 s 的形式给出。不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。
![](https://img-blog.csdnimg.cn/img_convert/e2a02176651e9a1acd8a79a0d2f09881.png)
思路
由于不能为另外的数组分配额外的空间,我想的思路是-->交换数组第一个元素和最后一个元素,再交换数组第二个元素和倒数第二个元素,交换到中间为止。
这也是双指针法的经典应用场景。
![](https://img-blog.csdnimg.cn/img_convert/7cf5067be42e81d7347b7636dee3daf4.gif)
代码
class Solution {
public:
void reverseString(vector<char>& s) {
int len = s.size();
for(int i=0,j=len-1;i<len/2;i++,j--){
swap(s[i],s[j]);
}
}
};
541. 反转字符串II
介绍
![](https://img-blog.csdnimg.cn/img_convert/dd0678c1f9e404fcb8b3b6b8355494e0.png)
思路
思路就是在复杂的规则下不断反转字符串。
![](https://img-blog.csdnimg.cn/img_convert/af0bb7e3b143aa3c305a4480fbf33b84.png)
for(i=0;i<s.size();i+=2k){
if(i+k<=s.size()){
reverse(s,i,i+k);//不包含i+k
conutiue;
}
reverse(s,i,s.size());//剩余部分不足k个
}
代码
class Solution {
public:
string reverseStr(string s, int k) {
for(int i=0;i<s.size();i = i+2*k){
if(i+k<=s.size()){
reverse(s.begin() + i, s.begin() + i + k );
continue;
}
reverse(s.begin() + i, s.end());
}
return s;
}
};
剑指Offer 05.替换空格
介绍
![](https://img-blog.csdnimg.cn/img_convert/e51157ecbed56f15ebba911787d11f79.png)
思路
这一类问题是数组填充类的问题,解决方法是预先给数组扩容到填充后的大小,然后从后向前进行操作。(双指针法)。
好处是:不用申请新数组、从后向前填充元素时,避免了从前向后填充元素时,每次添加元素都要将添加元素之后的所有元素向后移动的问题。
首先要统计空格的个数,然后再对原数组进行扩容,然后设立双指针从后往前遍历。
代码
class Solution {
public:
string replaceSpace(string s) {
//统计空格的个数
int count = 0;
int oldsize = s.size();
for(int i=0;i<s.size();i++){
if(s[i]==' '){
count++;
}
}
//扩充字符串s的大小
s.resize(oldsize + 2*count);
int newsize = s.size();
for(int i=newsize-1,j=oldsize-1;j<i ;i--,j--){
//注意j<i是条件,新数组的i一定是比旧数组的j大的,如果不满足该条件,那么就该跳出循环。
if(s[j]!=' '){
s[i] = s[j];
}else{
s[i] = '0';
s[i-1]='2';
s[i-2]='%';
i = i-2;
}
}
return s;
}
};
151.翻转字符串里的单词
介绍
![](https://img-blog.csdnimg.cn/img_convert/22837d336e627003aaf7f950e8f4f85e.png)
![](https://img-blog.csdnimg.cn/img_convert/12de57f83c957ca0ede1dcf454424119.png)
思路
![](https://img-blog.csdnimg.cn/img_convert/b309b2114c673d938babf3a450588586.png)
将源字符串进行一个整体的翻转,翻转后再对每一个单词进行翻转。
难点--> 删除多余的空格—双指针移除元素
定义一个快指针fastIndex,获取新数组中的元素
定义一个慢指针slowIndex,指向更新新数组下标的位置
开始的时候fastIndex移动,直到找到所要删除的元素后,给慢指针slowIndex赋值。将fastIndex++(指向后一个元素方便覆盖),然后将nums[fastIndex]的值赋给nums[slowIndex],再将fastIndex++,slowIndex++。
![](https://img-blog.csdnimg.cn/img_convert/f0378f1376bdfb71bed020139a25d0db.gif)
代码
class Solution {
public:
void removeExtraSpaces(string& s){
int slow = 0;
for(int fast=0;fast<s.size();++fast){
//遇到空格,直接++,即删除所有空格,即fast后移
//如果fast指向的位置不是空格
if(s[fast]!=' '){
//首先查看slow是否指向第一个元素,如果指向的不是第一个元素,则slow指向的位置要加空格。
if(slow!=0) s[slow++]=' ';
//然后就可以继续向后遍历,若fast指向的位置不是空格,则将其赋给slow,slow++,fast++
while(fast<s.size()&&s[fast]!=' '){
s[slow++] = s[fast++];
}
}
}
s.resize(slow);
}
void reverse(string &s,int start,int end){
for(int i=start,j=end;i<j;i++,j--){
swap(s[i],s[j]);
}
}
string reverseWords(string s) {
//去除原字符串多余的空格(首尾无空格,单词之间只有一个空格)
removeExtraSpaces(s);
//翻转整体字符串
reverse(s, 0, s.size() - 1);
//将翻转后的字符串中的每个单词翻转
int start = 0;
for (int i = 0; i <= s.size(); ++i) {
if (i == s.size() || s[i] == ' ') {
//到达空格或者串尾,说明一个单词结束。进行翻转。
reverse(s, start, i - 1); //i现在指向的位置是空格
start = i + 1; //下一个单词从空格的后一位i+1开始
}
}
return s;
}
};
剑指Offer58-II.左旋转字符串
介绍
字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部。请定义一个函数实现字符串左旋转操作的功能。比如,输入字符串"abcdefg"和数字2,该函数将返回左旋转两位得到的结果"cdefgab"。
![](https://img-blog.csdnimg.cn/img_convert/b8c193bec3f452712a8be1929c966600.png)
思路
反转区间为前n的子串
反转区间为n到末尾的子串
反转整个字符串
![](https://img-blog.csdnimg.cn/img_convert/e40c7b94c8e880c105609c8b1afb6e34.png)
代码
class Solution {
public:
string reverseLeftWords(string s, int n) {
reverse(s.begin(), s.begin() + n);
reverse(s.begin() + n, s.end());
reverse(s.begin(), s.end());
return s;
}
};