力扣(Leecode)151 刷题记录

一、题目信息

力扣链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

代码随想录:代码随想录

参考:代码随想录(卡哥yyds!!!!!!!!!!)

二、思路:

1. 先整体的来把字符串进行翻转:

abc defg -> gfed cba

2. 然后利用空格作为关键信息来对单个单词重新翻转一下:

 gfed cba -> defg abc

三、主要困难:

空格出现的位置很刁钻,而且个数也很难搞,比如说字符串

"   Hello    World   "

按照题目要求,字符应该以字母开始以字母结束,所以两端的这些空格都要灭掉;单词之间还只能保留一个空格,所以中间的空格也需要进行处理。

四、代码:

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]);
    }
    }

    string reverseWords(string s) {
        int slow_index = 0;
        int fast_index = 0;
        // 先想办法去掉字符串开头的空格 用快指针遍历到第一个非空的位置
        while(s[fast_index] == ' ')
        {
            fast_index ++;
        }
        // s[slow_index++] = s[fast_index]; // 找到了第一个不是空格的元素,就把这个值赋给慢指针  这个地方不对哦慢指针不用动
        for(; fast_index < s.size();fast_index++)
        {
            if(fast_index-1>0 && s[fast_index] == ' ' && s[fast_index-1] == ' ') // 这个地方的fast_index-1不能说来就来的,必须得考虑这个地方有没有超出范围,然后如果碰到了一个位于中间部位的空格还必须得保留一个,fast_index 第一次进入空格位置的时候slow_idex是直接把值读过去的,所以就有了一个空格,之后的fast就是要遍历找到下一个非空格的位置
            {
                continue; // 这个continue,直接跳过了之后的所有语句,也是很绝!
            }
            else
            {
                s[slow_index++] = s[fast_index];  
                // 这里注意,交换的是元素,不是元素和序号进行交换,我说为啥我换完之后一堆空格哈哈哈哈哈哈
            }
        }
        // 去掉末尾的空格  如果原始字符串的最后位置是一连串空格,那么我的slow_index 就不可避免读取到了一个空格,所所以我得看看循环终止之后我的slow_index指向的到底是什么

// 这里需要注意的是,如果原始字符串末尾还有好多空格的话,当上边的操作结束之后,s更新了最后一位,是个空格,而且slow_index也+1了。
// 因此在看字符串最后一位的时候,看的是slow-1,既然-1了,自然还要看是不是超范围

        if (slow_index - 1 > 0 && s[slow_index - 1] == ' ')
        {
            s.resize(slow_index-1);
        }
        else
        {
            s.resize(slow_index); // 重新设置字符串大小
        }
        reverse(s,0,s.size()-1);
        int start = 0; //removeExtraSpaces后保证第一个单词的开始下标一定是0。
        for (int i = 0; i <= s.size(); i++) {
            if (i == s.size() || s[i] == ' ') { //到达空格或者串尾,说明一个单词结束。进行翻转。
                reverse(s, start, i - 1); //翻转,注意是左闭右闭 []的翻转。
                start = i + 1; //更新下一个单词的开始下标start
            }
        }
        return s;



    }
};

五、代码说明:

1. 第一个环节定义了一个用来翻转字符串的函数,传入待翻转字符串,起始位置,终止位置,利用swap(a,b)实现字符串翻转;

2. 第二个环节实现对字符串的初加工,去除首位空格,以及单词之间的空格,采用双指针法。

2.1 起始空格处理:快慢指针均指向0位置,快指针向后遍历至遇到第一个不为空格的字符,赋值给慢指针指向的字符串位置

2.2 中间空格处理:利用判断条件 if(fast_index-1>0 && s[fast_index] == ' ' && s[fast_index-1] == ' '),如果快指针遍历过程中发现刚刚遍历的位置(fast-1)是个空格,fast位置还是空格,那就continue跳过去,继续往前走,否则就要给慢指针指向的位置赋值了;

2.3 末尾空格处理:当fast指针遍历结束之后,slow更新s的过程也就停止了,需要注意的是,在我的这个程序里边尽管s不再更新了,但是slow还是自加1了,这个地方导致我错了好多次……蠢哭了。而且如果原始字符串末尾有空格,那么更新之后的字符串末尾也保留了一个空格,需要后边进行处理

3. 第三个环节要对字符串长度进行更新,在处理之前,需要看字符串末位是不是空格,此时的字符串末尾对应的是slow-1!!!,如果是空格,那resize的时候就是slow-1,否则就是slow,这个size返回的是整个s的长度,所以slow作为序号是比这个size大1的

4. 第四个环节,以空格为标志,定义快慢指针对单词在进行一遍翻转。

end!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值