day8
344.反转字符串
建议: 本题是字符串基础题目,就是考察 reverse 函数的实现,同时也明确一下 平时刷题什么时候用 库函数,什么时候 不用库函数
题目链接/文章讲解/视频讲解:programmercarl.com/0344.%E5%8F…
个人思路: 该题特别基础,只需要遍历一次数组,将对应位置(a[0]---a[n])进行交换即可。
代码:
class Solution {
public:
void reverseString(vector<char>& s) {
int n = s.size();
int halfn =n/2;
int L = 0;
int R = n-1;
while(L<R)
{
char tmp;
tmp=s[L];
s[L]=s[R];
s[R]=tmp;
L++;
R--;
}
return ;
}
};
541. 反转字符串II
建议:本题又进阶了,自己先去独立做一做,然后在看题解,对代码技巧会有很深的体会。
题目链接/文章讲解/视频讲解:programmercarl.com/0541.%E5%8F…
个人思路:
本题采用了一次计数器去统计字符串的个数,其实没有必要,由于在每次处理中都是针对i+2k内的元素进行处理,因此每次将数组的下标移动2k即可(见代码1)。
代码1:
class Solution {
public:
string reverseStr(string s, int k) {
for (int i = 0; i < s.size(); i += (2 * k)) {
// 1. 每隔 2k 个字符的前 k 个字符进行反转
// 2. 剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符
if (i + k <= s.size()) {
reverse(s.begin() + i, s.begin() + i + k );
} else {
// 3. 剩余字符少于 k 个,则将剩余字符全部反转。
reverse(s.begin() + i, s.end());
}
}
return s;
}
};
代码2:
class Solution {
public:
string reverseStr(string s, int k) {
int n =s.size();
int count =0;
for(int i =1;i<=n;i++)
{
count++;
if(count==2*k)
{
int L = i-2*k;
int R = i-k-1;
while(L<R)
{
swap(s[L],s[R]);
L++;
R--;
}
count=0;
}
}
if(count<2*k&&count>=k)
{
int L = n - count;
int R = L + k-1;
while(L<R)
{
swap(s[L],s[R]);
L++;
R--;
}
}else if(count<k)
{
int L = n - count;
int R = n-1;
while(L<R)
{
swap(s[L],s[R]);
L++;
R--;
}
}
return s;
}
}
剑指Offer 05.替换空格
建议:对于线性数据结构,填充或者删除,后序处理会高效的多。好好体会一下。
题目链接/文章讲解:programmercarl.com/%E5%89%91%E…
个人思路: 本题是剑指Offer里面的第一道编程题,地位不亚于单词书里面的abandon:)。该题的主要思路是首先遍历整个字符串,计算出空格的个数,然后根据空格的个数扩充字符串的大小,然后从后往前遍历,填入对应的字符。
代码:
class Solution {
public:
string replaceSpace(string s) {
int n = s.size();
int conut = 0;
for(int i =0;i<n;i++)
{
if(s[i]==' ') conut++;
}
int newsize = n+conut*2;
s.resize(s.size() + conut * 2);
int R = newsize-1;
int L = n-1;
while(conut&&L<R)
{
if(s[L]!=' ') {
s[R--] =s[L--];
}else{
s[R--]='0';
s[R--]='2';
s[R--]='%';
L--;
conut--;
}
}
return s;
}
};
151.翻转字符串里的单词
建议:这道题目基本把 刚刚做过的字符串操作 都覆盖了,不过就算知道解题思路,本题代码并不容易写,要多练一练。
题目链接/文章讲解/视频讲解:programmercarl.com/0151.%E7%BF…
个人思路: 该题的做法是先将整个字符串进行翻转,然后再单独的将字符提取出来,单独对字符进行翻转。主要的难点在于对空格的处理,采用双指针的办法处理空格,首先是处理前导0,快指针记录第一个不为空格的字符,将其全部移动慢指针对应的位置(慢指针从0开始),处理中间的思路与上述类似,记住处理s[j-1]和s[j]保证处理后有一个空格,处理完所有元素后,将最后的空格进行截断,移动元素的思路类似。
代码:
class Solution {
public:
// void reverse(string& s, int start, int end){ //翻转,区间写法:左闭又闭 []
// for (int i = start, j = end; i < j; i++, j--) {
// swap(s[i], s[j]);
// }
// }
void removespace(string& s){
int n = s.size();
int i =0;
int j =0;
while(1){ //j对应为字符串s中第一个不为0的下标
if(s[j]!=' ') break;
j++;
}
while(j<n){
if(j-1>0 && s[j]==' '&& s[j-1]==s[j])
{
j++;
}
else
{
s[i++]=s[j++];
}
}
if(i-1>0&&s[i-1]==' ') s.resize(i-1);
else s.resize(i);
return;
}
string reverseWords(string s) {
int n = s.size();
int L = 0;
int R = n-1;
while(L<R){
swap(s[L],s[R]);
L++;
R--;
}
removespace(s);
cout<<s;
int start = 0; //removeExtraSpaces后保证第一个单词的开始下标一定是0。
for (int i = 0; i <= s.size(); ++i) {
if (i == s.size() || s[i] == ' ') { //到达空格或者串尾,说明一个单词结束。进行翻转。
int L = start;
int R = i-1;
while(L<R)
{
swap(s[L],s[R]);
L++;
R--;
}
//reverse(s, start, i - 1); //翻转,注意是左闭右闭 []的翻转。
start = i + 1; //更新下一个单词的开始下标start
}
}
return s;
}
};
剑指Offer58-II.左旋转字符串
建议:题解中的解法如果没接触过的话,应该会想不到
题目链接/文章讲解:programmercarl.com/%E5%89%91%E…
**个人思路:**具体步骤为:
- 反转区间为前n的子串
- 反转区间为n到末尾的子串
- 反转整个字符串
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;
}
};