代码随想录(day8)——字符串
Leetcode.344 反转字符串:
344. 反转字符串 - 力扣(LeetCode)
原理过于简单,没什么好说的,直接给出代码:
class Solution {
public:void reverseString(vector<char>& s) {int end = s.size()-1;int start = 0;while( start <= end){swap(s[start],s[end]);start++;end--;}}
};
Leetcode.541 反转字符串:
541. 反转字符串 II - 力扣(LeetCode)
对于本题,题干中的条件看起来十分复杂,其实可以归结于一种分支情况,即每次都读取给定字符串中的前
个字符,反转前
个。即:
而下面的两行则只是针对字符串中的剩余字符。如果剩余字符的数量少于则全部反转,否则反转前
个。
由于对于字符串的反转,每次都是以来进行的,所以,在遍历整体的字符串时,每次都遍历
个字符,再对这些字符进行操作。由于每当读取
字符和剩余字符的数量
,
时,都是反转
个字符,所以这两种情况可以归为一类。即:判断已被操作的区间+
是否满足
,满足的话,则反转这段区间的前
字符,否则说明剩余字符的数量
,因此,直接对剩余的字符全部进行反转即可。
class Solution {
public:string reverseStr(string s, int k) {for(int i = 0; i < s.size(); i+=2*k){if(i + k <= s.size()){reverse(s.begin()+i,s.begin()+i+k);}else{reverse(s.begin()+i,s.begin()+s.size());}} return s; }
};
卡码网.54 替换数字:
54. 替换数字(第八期模拟笔试) (kamacoder.com)
对于本题,可以直接利用中的运算符重载
以及开辟一个新的
类对象来完成,但是这种方法需要开辟新的空间,且过于简单,意义不大,因此对于这种方法本处只给出代码,重点在于下面的第二种方法:
#include<string>
#include<iostream>
using namespace std;int main()
{string s1,s2;cin >> s1;for(int i = 0; i < s1.size(); i++){if(s1[i] >= '0' && s1[i] <= '9'){s2+="number";}else{s2+=s1[i];}}cout << s2;return 0;
}
运行结果如下:
对于第二种方法,可以首先遍历一遍给定的字符串,并且创建一个变量用于统计给定字符串中出现数字的次数。在遍历完成后,直接利用
函数对给定字符串进行扩容,扩容大小为
,即
。此时的字符串的大小就等于将所有的数字都改为
后的字符串的大小。
然后利用双指针对字符串进行遍历,一个指针指向现字符串的末尾,另一个指针
指向原字符串最后一个字符所在的位置。例如对于字符串
,由于字符串中存在三个数字,因此
,在扩容时,大小为
。双指针指向的位置如下图所示:
如果位置所对应的字符是数字,则从
位置开始,依次向前填写
的每个字母,即:
在完成对于的倒序填写后,令
,即:
再对位置的字符进行判断,由于不为数字,因此
对
位置进行赋值。即:
随后再。依次循环即可。
对应代码如下:
#include<string>
#include<iostream>
using namespace std;int main()
{string s1;cin >> s1;int count = 0;for(int i = 0; i < s1.size(); i++){if(s1[i] >= '0' && s1[i] <= '9'){count++;}}int oldlen = s1.size()-1;int slow = oldlen;s1.resize(s1.size()+5*count);int fast = s1.size()-1;for(; fast >=0; fast--){if(s1[slow] >= 'a' && s1[slow] <= 'z'){s1[fast] = s1[slow];}else {s1[fast] = 'r';s1[fast-1] = 'e';s1[fast-2] = 'b';s1[fast-3] = 'm';s1[fast-4] = 'u';s1[fast-5] = 'n';fast-=5;}slow--;}cout <<s1;return 0;
}
Leetcode.151 反转字符串中的单词:
151. 反转字符串中的单词 - 力扣(LeetCode)
对于本题,与文章C及C++每日练习(2)-CSDN博客中倒置字符串一题极为相似,但是对于本题,单词之间的空格并不是只有一个,而是若干个。因此,解决本题的方法可以分为两步:
1.将给定字符串中的多余的空格进行删除。
2.按照C及C++每日练习(2)-CSDN博客中的方法倒置字符串中的单词
对于如何删除字符中多余的空格,例如对于下面给定的字符串:
对于多余的字符,分别为第一个字符前面的空格和最后一个字符后面的空格,以及两个单词之前非第一个空格。对于消除多余的字符,可使用的方法如下:
利用循环对字符串进行遍历,同时创建两个指针
.在循环中,只对
的情况进行处理,如果
则令
继续向后遍历。例如对于上面图中的字符串,
的起始位置如下所示:
当时,即:
令,并且两个指针向后移动一位,即:
按照上述方法,利用循环完成对于单个字符或者字符串的覆盖,即:
while(fast < s.size() && s[fast] != ' '){s[slow++] = s[fast++];}
而对于多余空格的处理,可以再循环开头单独进行判定:判定条件如下:,例如对于上面图中
所处的位置是待处理的多余空格。由于处理多个空格的条件为
,因此按照前面对于
运动逻辑的规定,
会继续向下遍历,直到找到非空字符,即:
此时,改变位置的字符,即:
,然后让
指向下一个位置,即:
随后,再利用前面的逻辑使得来复写非空字符串,即:
再按照前面的规则,首先让移动至非空字符,即:
令,即:
再复写非空字符串,即:
完成了对于字符串的去重操作。随后,利用函数,将字符串的长度改为
。
对于旋转字符串的方法,可以在C及C++每日练习(2) 进行查看,本处只给出相应代码:
class Solution {
public:void removeExtraSpace(string&s){int slow = 0, fast = 0;for(fast= 0;fast < s.size(); fast++){if(s[fast] != ' '){if(slow != 0){s[slow] = ' ';slow++;}}while(fast < s.size() && s[fast] != ' '){s[slow++] = s[fast++];}}s.resize(slow);}string reverseWords(string s) {removeExtraSpace(s);reverse(s.begin(),s.end()); int slow = 0;for(int fast = 0; fast <= s.size(); fast++){if(fast == s.size() || s[fast] == ' '){reverse(s.begin()+slow,s.begin()+fast);slow = fast+1;}}return s;}
};
运行结果如下:
卡码网.55 右旋字符串:
55. 右旋字符串(第八期模拟笔试) (kamacoder.com)
没什么好说的,先整体逆置,在前个逆置,最后剩余的逆置,代码如下:
#include<iostream>
#include<string>
#include<algorithm>
using namespace std;int main()
{int k = 0;string s;cin>>k;cin>>s;reverse(s.begin(),s.end());reverse(s.begin(),s.begin()+k);reverse(s.begin()+k,s.end());cout << s;return 0;
}
运行结果如下: