leetcode151-Reverse Words in a String(翻转字符串单词的位置)

本篇博客详细介绍了LeetCode 151题——翻转字符串中单词的位置。内容涵盖问题描述、两种解法(包括需要辅助空间和不需要辅助空间的方法)以及对字符串的扩展变形处理,如保留首尾空格并翻转单词的大小写。

1、问题描述:

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

For example,

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

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.
应该处理两单词间连续多个空格的情况,使其只包含一个

2、问题求解:

方法一:O(n)时间,并且需要辅助空间O(n)

class Solution {
public:
    void reverseWords(string &s) {//如s为“the sky”
        int n=s.size();
        int i=n-1;
        //辅助字符串存放结果字符串
        string stmp="";//最后为“sky the”
        while(i >= 0)
        {
            while(s[i]==' ' && i>=0)
            {//(1)处理连续有多个空格的情况
                i--;
            }
            if(i<0) break;//s处理完空格,若后续没有单词则应跳出循环
            string wordtmp="";
            for(;i>=0 && s[i]!=' ';i--)
            {//(2)从后往前遍历,每次取得一个单词赋给wordtmp
                wordtmp += s[i];
            }//第一个单词为yks
            //(3)翻转wordtmp,如yks
            reverse(wordtmp.begin(), wordtmp.end());
            if(stmp != "")
            {//(4)在将翻转后的单词加入到stmp之前先加入空格(若非首单词)
                stmp.append(" ");
            }
            stmp.append(wordtmp);//(5)加入到stmp
        }
        s=stmp;
    }
};

方法二:O(n)时间,不需要辅助空间

(1)从前往后遍历,依次翻转每个单词
(2)翻转整个字符串

class Solution {
public:
    void reverseWords(string &s) {
        int n=s.size();
        int i=0, j=0;
        int start=0;
        while(i<n)
        {
            while(i<n && s[i]==' ') i++;//(1)处理空格
            if(i<n && j>0)
            {//(2)如果处理到非首单词(j>0),要在其前加入空格
                s[j++]=' ';
            }
            //(3)翻转每个单词
            start=j;
            while(i<n && s[i]!=' ')
            {
                s[j++]=s[i++];
            }
            reverse(s.begin()+start, s.begin()+j);
        }
        s.resize(j);//(4)重置s大小
        reverse(s.begin(), s.end());//(5)翻转整个字符串
    }
};

3、扩展:

对于一个给定的字符串,我们需要在线性(也就是O(n))的时间里对它做一些变形。首先这个字符串中包含着一些空格,就像”Hello World”一样,然后我们要做的是把着个字符串中由空格隔开的单词反序,同时反转每个字符的大小写。比如”Hello World”变形后就变成了”wORLD hELLO”。

分析:该题与上题的区别是不丢弃字符串前后的空格,只不过翻转后后边的空格放到前面,而前面的空格放到后面;再就是单词大小写转换。

#include <iostream>
#include<string.h>
#include<algorithm>
using namespace std;

class Transform {
public:
    string trans(string s, int n) {
        int i=n-1;
        //辅助字符串存放结果字符串
        string stmp="";//最后为“sky the”
        while(i >= 0)
        {//从后往前
            while(s[i]==' ' && i>=0)
            {//(1)见到空格就放入stmp(后面的空格最终放到前面,单词之间的空格也会放入)
                stmp.append(" ");//!!!
                i--;
            }
            //if(i<0) break;//s处理完空格,若后续没有单词则应跳出循环
            string wordtmp="";
            for(;i>=0 && s[i]!=' ';i--)
            {//(2)从后往前遍历,每次取得一个单词赋给wordtmp
                wordtmp += s[i];
            }//第一个单词为yks
            //(3)翻转wordtmp,如yks
            reverse(wordtmp.begin(), wordtmp.end());
            /*
            if(stmp.find_first_not_of(" ")!=string::npos || stmp!="")
            {//(4)在将翻转后的单词加入到stmp之前先加入空格(若非首单词)
                stmp.append(" ");
            }*/
            stmp.append(wordtmp);//(5)加入到stmp
        }
        s=stmp;
        cout<<s<<" "<<s.size()<<endl;
        //(4)下边用于转换大小写
        i=0;
        while(i<n)
        {
            if(s[i]==' ') i++;
            else
            {
                s[i]=isupper(s[i])?tolower(s[i]):toupper(s[i]);
                i++;
            }
        }
        return s;
    }
};

int main()
{
    Transform t;
    string str="  We are champion";
    //string str1=" h i";
    int n=str.size();
    cout<<n<<endl;
    string res=t.trans(str, n);
    cout<<res<<endl;
    return 0;
}

结果:

17
champion are We   17
CHAMPION ARE wE

Process returned 0 (0x0)   execution time : 2.889 s
Press any key to continue.

即翻转后字符串大小不变。

若输入"  We are champion",则输出"CHAMPION ARE wE  ".
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值