目录
ps:定义函数对字符串进行修改的时候,形参那里总是忘记加引用符号&!
一、344.反转字符串
1.解题思路(双指针法)
题目要求空间复杂度为O(1),因此这里不能再开辟一个数组,然后原数组从后往前向新数组赋值。
这里使用双指针法,定义两个指针,指针1指向第一个元素,指针2指向最后一个元素,然后将这两个元素交换,交换完成之后,更新双指针的位置。
2.代码实现(双指针法)
这里交换两个元素可以用以下方法:
①直接调用swap函数
②定义一个临时变量temp,利用temp交换两个元素
③使用异或操作符1.
class Solution {
public:
void reverseString(vector<char>& s) {
for(int i = 0,j = s.size() - 1;i < j;){
s[i] ^= s[j];
s[j] ^= s[i];
s[i] ^= s[j];//用异或操作符来完成元素交换
i++;
j--;//交换完成之后,双指针向中间移动
}
}
};
二、541. 反转字符串II
1.解题思路
for循环,每次i移动2k。不要固化思维每次做i++操作,然后再搞个计数器,统计什么时候达到2k次。
①2k个字符前k个反转
②如果剩余字符<2k但是>=k,则反转前k个
③剩余字符少于k个,就全部反转,从开始位置i到字符串末尾
2.代码实现
这里没有用库函数reverse()。自己重新定义了reverse函数,可以左闭右开,左闭右闭。
class Solution {
public:
void myReverse(string& s,int begin,int end){//定义自己的reverse函数,左闭右开
for(int i = begin,j = end - 1;i < j;){
s[i] ^= s[j];
s[j] ^= s[i];
s[i] ^= s[j];
i++;
j--;
}
}
string reverseStr(string s, int k) {
for(int i = 0;i < s.size();i += 2 * k){//注意这里i每次移动2k个
//如果这个区间有>= k个字符,就交换前k个字符
if(i + k <= s.size()){
myReverse(s,i,i + k);
}
else{//剩余字符小于k个,就全部反转
myReverse(s,i,s.size());
}
}
return s;
}
};
三、剑指Offer 05.替换空格
1.解题思路(双指针法)
统计空格个数,然后对原数组扩容:因为是将空格换成“%20”,所以要对数组扩容 (2*空格个数)。
然后定义双指针,分别指向原数组最后一个元素和新数组最后一个元素,然后赋值。
2.代码实现(双指针法)
class Solution {
public:
string replaceSpace(string s) {
int sOldsize = s.size();//保存数组原来长度
int count = 0;//统计空格的数量,然后对数组做相应的扩容
for(int i = 0;i < s.size();i++){
if(s[i] == ' ')
count++;
}
s.resize(sOldsize + count * 2);//resize原数组
int sNewsize = s.size();//保存当前数组长度
for(int i = sOldsize - 1,j = sNewsize - 1;i < j;i--,j--){
if(s[i] != ' '){//如果i指向空格了,就替换成"%20"
s[j] = s[i];
}
else{
s[j--] = '0';
s[j--] = '2';
s[j] = '%';
}
}
return s;
}
};
四、151.翻转字符串里的单词
1.题目描述
给你一个字符串 s
,请你反转字符串中 单词 的顺序。
单词 是由非空格字符组成的字符串。s
中使用至少一个空格将字符串中的 单词 分隔开。
返回 单词 顺序颠倒且 单词 之间用单个空格连接的结果字符串。
注意:输入字符串 s
中可能会存在前导空格、尾随空格或者单词间的多个空格。返回的结果字符串中,单词间应当仅用单个空格分隔,且不包含任何额外的空格。
示例 1:
输入:s = "the sky is blue
" 输出:"blue is sky the
"
2.解题思路
①题目字符串s中每个单词之间的空格可能不止一个,因此这道题目的第一步,就是将单词之间多余的空格给删除掉:使用双指针法,fast在前,slow在后,如果fast指向的是我们想要的元素,就赋值给slow(记得每个单词要用空格分隔)
② 两次reverse,第一次reverse整体,第二次reverse每个单词,这样得到的结果就是题目要求的了。
3.代码实现
class Solution {
public:
//解题总体步骤
//1.移除多余空格(双指针法),用erase函数时间复杂度太高
//2.反转整个字符串
//3.反转每个单词
void removeExtraSpaces(string& s){//function:移除多余空格
int fast = 0,slow = 0;//定义快慢指针
for(fast = 0;fast < s.size();fast++){
//只要快指针fast指向的是我们需要的元素,就赋值给slow
if(s[fast] != ' '){
if(slow != 0){//如果slow所指向的不是第一个单词,就要先给一个空格
s[slow++] = ' ';
}
//补全这个单词
while(fast < s.size() && s[fast] != ' '){
s[slow++] = s[fast++];
}
}
}
s.resize(slow);//注意这里要对字符串更新长度,目前长度为slow
}
void myReverse(string& s, int begin,int end){//function:反转指定长度的字符串.
//区间:左闭右开
int left = begin,right = end - 1;
for(;left < right;left++,right--){
s[left] ^= s[right];
s[right] ^= s[left];
s[left] ^= s[right];
}
}
string reverseWords(string s) {
//1.移除多余空格(双指针法),用erase函数时间复杂度太高
removeExtraSpaces(s);
//2.反转整个字符串
myReverse(s,0,s.size());
//3.反转每个单词
int start = 0;//标记每个单词的起始位置
for(int i = 0;i <= s.size();i++){//当i指向空格或者字符串末尾,表示一个单词结束,对该单词进行反转
if(s[i] == ' ' || i == s.size()){
myReverse(s,start,i);
start = i + 1;//更新下一个单词的起始位置
}
}
//返回结果
return s;
}
};
五、剑指Offer58-II.左旋转字符串
1.题目描述
字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部。请定义一个函数实现字符串左旋转操作的功能。比如,输入字符串"abcdefg"和数字2,该函数将返回左旋转两位得到的结果"cdefgab"。
示例 1:
输入: s = "abcdefg", k = 2
输出: "cdefgab"
示例 2:
输入: s = "lrloseumgh", k = 6
输出: "umghlrlose"
限制:
1 <= k < s.length <= 10000
2.解题思路
如果题目给的数字为n,
只需三步骤:
①反转前n个字符的子串
②反转n到字符串末尾的子串
③反转整个字符串
3.代码实现
class Solution {
public:
void myReverse(string& s,int begin,int end){
for(int i = begin ,j = end - 1;i < j;i++,j--){
s[i] ^= s[j];
s[j] ^= s[i];
s[i] ^= s[j];
}
}
string reverseLeftWords(string s, int n) {
//反转前n个字符
myReverse(s,0,n);
//反转后面的字符
myReverse(s,n,s.size());
//反转整个字符串
myReverse(s,0,s.size());
return s;
}
};