LeetCode -- Reverse Words in a String

本文探讨了如何通过多种方法实现字符串单词级别的逆序操作,重点介绍了使用栈和双指针技巧来处理空格和多词间隔。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目如下:

Given an input string, reverse the string word by word.

For example,
Given s = "the sky is blue",
return "blue is sky the".

click to show clarification.

Clarification:

  • What constitutes a word?
    A sequence of non-space characters constitutes a word.
  • Could the input string contain leading or trailing spaces?
    Yes. However, your reversed string should not contain leading or trailing spaces.
  • How about multiple spaces between two words?
    Reduce them to a single space in the reversed string.
-----------------------------------------------------------------------------------------------------------------------------------------

这道题目难度不是很大,但是坑比较多,一个是首尾的空字符要处理掉,另一个是中间间隔的空字符可能不是一个字符,另外是否有用‘\t'或其他的作为间隔符没有仔细考证,如果单词之间有多个空格的话,也要把他们缩减为一个空格。

如果有split函数的话,就比较好解决。

乍一看,想到一个思路:可以用一个栈来保存每个单词,由于栈有后进先出的性质,出栈后的顺序刚好逆序,符合题目的要求。

class Solution {
public:
    void reverseWords(string &s) {
        stack<string> stk;
        string wrd = "";
        int pre = -1, cnt = -1, i = 0;
        
        for(i = 0; i < s.length(); ++i)
        {
            if(s[i] == ' ' || s[i] == '\r' || s[i] == '\t' || s[i] == '\n')
            {
                if(pre >= 0 && cnt > 0){
                    wrd = s.substr(pre, cnt);
                    stk.push(wrd);
                }
                pre = -1;
                cnt = -1;
            }else{
                if(cnt == -1 && pre == -1)
                {
                    cnt = 1;
                    pre = i;
                }else
                    ++cnt;
            }
        }
        if(pre >= 0 && cnt > 0)
        {
            wrd = s.substr(pre, cnt);
            stk.push(wrd);
        }
        string ret = "";
        int first = 1;
        while(!stk.empty())
        {
            wrd = stk.top();
            stk.pop();
            if(first == 1){
                ret += wrd;
                first = 0;
            }else
                ret += " " + wrd;
        }
        s = ret;
    }
};
这段代码比较长,主要是用pre记录第一个非空格的字符,用cnt记录单词的长度,每找到一个单词就放入栈,找完以后再出栈存到字符串中即可。


隔了一段时间之后,我又写下了另外一种解法:用两个位置变量pre和p分别记录单词两段空格的位置,这样用substr就能提取单词。然后直接逆序放到另一个字符串保存。

class Solution {
public:
    void reverseWords(string &s) {
        size_t pre = -1, p;
        while((pre+1) < s.length() && (s[pre+1] == ' ' || s[pre+1] == '\t'))++pre;
        p = pre + 1;
        string ss = s;
        s = "";
        int flag = 1;
        while(p < ss.length()){
            while(p < ss.length() && ss[p] != ' ' && ss[p] != '\t')++p;
            if(flag == 0){
                s = ss.substr(pre+1, p-pre-1) + " " + s;
            }else{
                s = ss.substr(pre+1, p-pre-1);
                flag = 0;   
            }
            pre = p;
            while((pre+1) < ss.length() && (ss[pre+1] == ' ' || ss[pre+1] == '\t'))++pre;
            p = pre+1;
        }
    }
};
这里要注意的是,结果如果只有一个单词的话,就不要空格字符串。两个单词之间才需要一个空格。另外首尾的空格也要处理。


上面的代码还是稍微有点长,下面有个更加简化的版本:

class Solution {
public:
    void reverseWords(string &s) {
        string b = "", t = "";
        size_t  j = 0;
        while(j < s.length() && (s[j] == ' ' || s[j] == '\t')) ++j;
        while(j < s.length()){
            while(j < s.length() && s[j] != ' ' && s[j] != '\t')t += s[j++];
            b = t + " " + b;
            t = "";
            while(j < s.length() && (s[j] == ' ' || s[j] == '\t'))++j;
        }
        s = b.substr(0, b.length()-1);
    }
};
第一个while循环处理开头的空字符,每个单词后面都带上一个空格,最后返回结果的时候把最后一个单词后面的空格去掉就可以。

写这段代码的时候遇到一个坑:size_t是无符号的类型,我开始将一个变量赋值为-1,导致变量的值被转化为整数,以至于最后的结果很奇怪,不注意的话也是比较难看出来的。







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值