344.反转字符串
随想录文字讲解:代码随想录 (programmercarl.com)
随想录视频讲解:字符串基础操作! | LeetCode:344.反转字符串_哔哩哔哩_bilibili
状态:做出来了
双指针秒了,没啥可说的
541. 反转字符串II
随想录文字讲解:代码随想录 (programmercarl.com)
随想录视频讲解:字符串操作进阶! | LeetCode:541. 反转字符串II_哔哩哔哩_bilibili
状态:有bug没找出来
自己的写法比较复杂,初始化一个指针指向头部,然后每次加2k来看是否出界来循环,循环体内反转字符串。出循环后判断剩余字符串情况再反转。
但我在交换时出现了数组越界的错误,我原来的写法:
for(int i=0;i<k/2;i++)
swap(s[left++],s[right--]);
改正后:
for(int i=left,j=right;i<j;i++,j--)
swap(s[i],s[j]);
随想录做法:
随想录做法将几种情况全放在一个循环里,我的做法是先判断不溢出情况,再判断末尾,而随想录的遍历是使头指针以2k长度前进。
i += (2 * k)
遍历时去判断i+k是否超出数组,不超出就直接反转,然后跨过一个2k。如果超出就直接反转剩余字符。
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;
}
};
卡码网:54.替换数字
随想录文字讲解:代码随想录 (programmercarl.com)
将数字替换为number应遍历数字数量然后扩容,然后一个指针指向原字符串末尾,一个指向扩容后的末尾,开始遍历,指针指向数字就让扩容数组指针填充number,然后前走5格。不是数字就正常赋值。
151.翻转字符串里的单词
随想录文字讲解:151. 反转字符串中的单词 - 力扣(LeetCode)
随想录视频讲解:字符串复杂操作拿捏了! | LeetCode:151.翻转字符串里的单词_哔哩哔哩_bilibili
状态:做出来了
看到这道题的想法是创立一个新字符串,然后把旧字符串中遍历找到的单词一个个从后加进去。
于是就有如下几个问题需要解决:1.如何找到单词。2.填充新数组时如何把单词加进去。
对于问题1,是比较常见的解法,只要遍历数组然后根据是否为空格就能找到每个单词所在的位置。从头节点开始遍历,如果是空格就++,直到找到第一个不为空格的字符,即为单词的首字母,然后寻找该字母后的第一个空格,空格前一位即是该单词的最后一个字母,循环往复直到遍历完整个字符串。(注意,这里有一个边界条件,在寻找空格后的第一个字母时,如果一直找到字符串末尾都没找到,即都是尾随空格,此时退出循环。)
如何添加单词:在遍历时,可用指针确定单词的位置。所以我用pair来存储单词,first存储首字母所在指针,second存储尾字母指针。读取pair即可填入单词,由于是颠倒且要确定填充次数,预设设立一个stack<pair<int,int>>容器,遍历原字符串时读取单词,然后再逐个读出栈里元素。
由于每个单词间有空格,便在添加单词后再加一个空格,出栈结束后删掉末尾空格。
代码如下:
class Solution {
public:
string reverseWords(string s) {
stack<pair<int,int>> p;
int a,b;
for(int i=0;i<s.size();i++)
{
while(i<s.size()&&s[i]==' ') i++;
if(i==s.size()) break;
a=i;
while(i<s.size()&&s[i]!=' ') i++;
b=i-1;
p.push({a,b});
}
string t;
while(!p.empty())
{
for(int i=p.top().first;i<=p.top().second;i++)
t.push_back(s[i]);
t.push_back(' ');
p.pop();
}
t.erase(t.end() - 1);
return t;
}
};
随想录做法:
先将整个字符串去除多余空格,再翻转字符串,翻转后再将每个单词翻转过来,即可得到结果。
时间复杂度为o(n),空间复杂度为o(1),我的做法时间复杂度为o(n),空间复杂度则要更高一些(因为我使用了新string)
在去除空格时,使用了双指针的算法,当快指针不指向空格时,如果慢指针此时不为0,就填一个空格(该空格为单词间的空格,不为0是避免出现前导空格),然后填充单词直至快指针指向空格。代码如下:
int slow=0;
for(int i=0;i<s.size();i++)
{
if(s[i]!=' ')
{
if(slow!=0) s[slow++]=' ';
while(i<s.size()&&s[i]!=' ')
s[slow++]=s[i++];
}
}
最后别忘了缩减大小: s.resize(slow);
然后翻转一次字符串,再开始翻转单词:
每当i指针走到空格时,就翻转前面的字符串(即一个单词),然后更新单词头部指针,当指针走到字符串尾部时,也进行一次翻转(或条件)
int k=0;
for(int i=0;i<=s.size();i++)
{
if(i==s.size()||s[i]==' ')
{
reverse(s,k,i-1);
k=i+1;
}
}
复现代码的时候,写完了一直输出的字符串没变,然后发现leetcode中的函数参数不是引用,改一下就过了
卡码网:55.右旋转字符串
随想录文字做法:代码随想录 (programmercarl.com)
状态:照着随想录做的
想不出来怎么在o(1)空间内完成,所以就没写。
看完随想录的做法复现做的,要把数组最右面放到最左面,就先把整个数组倒序一遍,再对两个部分分别倒序恢复原状,妙啊。
没课的一天,但是让我过的稀碎,唉。