代码随想录算法训练营第八天|344.反转字符串● 541. 反转字符串II● 卡码网:54.替换数字● 151.翻转字符串里的单词● 卡码网:55.右旋转字符串

 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)空间内完成,所以就没写。

看完随想录的做法复现做的,要把数组最右面放到最左面,就先把整个数组倒序一遍,再对两个部分分别倒序恢复原状,妙啊。


没课的一天,但是让我过的稀碎,唉。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值