剑指Offer--042-翻转单词顺序列

链接


牛客OJ:翻转单词顺序列

九度OJ:http://ac.jobdu.com/problem.php?pid=1361

GitHub代码: 042-翻转单词顺序列

CSDN题解:剑指Offer–042-翻转单词顺序列

牛客OJ九度OJCSDN题解GitHub代码
042-翻转单词顺序列1361-翻转单词顺序列剑指Offer–042-翻转单词顺序列042-翻转单词顺序列


您也可以选择回到目录-剑指Offer–题集目录索引

题意


题目描述

牛客最近来了一个新员工Fish,每天早晨总是会拿着一本英文杂志,写些句子在本子上。同事Cat对Fish写的内容颇感兴趣,有一天他向Fish借来翻看,但却读不懂它的意思。例如,“student. a am I”。后来才意识到,这家伙原来把句子单词的顺序翻转了,正确的句子应该是“I am a student.”。Cat对一一的翻转这些单词顺序可不在行,你能帮助他么?

样例输入

student. a am I

I’m a Freshman and I like JOBDU!

样例输出

I am a student.

JOBDU! like I and Freshman a I’m

先翻转所有字符,再逐个单词翻转


这道题主要思想就是先翻转所有字符,再逐个单词翻转

然后是如何查找到每个单词,用指针left和right维护单词的起始位置和结束位置

如果当前遇到一个空格,说明发现了一个单词

如果找到了单词的最后,而末尾字符不是空格,说明字符串的末尾也是一个单词

通过翻转函数来实现


#include <iostream>

using namespace std;

//  调试开关
#define __tmain main

#ifdef __tmain

#define debug cout

#else

#define debug 0 && cout

#endif // __tmain

class Solution
{
public:
    string ReverseSentence(string str)
    {
        if(str.size( ) == 0)
        {
            return "";
        }

        //  首先翻转整个句子
        Reverse(str, 0, str.size( ) - 1);

        //  紧接着查找到每个单词, 然后翻转它
        int left = 0, right = 0;
        while(right <= str.size( ))
        {
            //  当遇见空格的时候说明找到了一个单词
            //  当走到字符串的最后一个位置, 那么前面如果不是空格, 那么最后也会有一个单词
            if((str[right] == ' ')
            || (right == str.size( ) && str[right - 1] != ' '))
            {
                /*
                for(int i = left; i < right; i++)
                {
                    debug <<str[i];
                }
                debug <<endl;
                */

                Reverse(str, left, right - 1);

                left = right + 1;
            }
            right++;
        }

        return str;
    }

    void Reverse(string &str, int left, int right)
    {
        while(left < right)
        {
            swap(str[left], str[right]);

            left++;
            right--;
        }
    }

    void Reverse(string::iterator left, string::iterator right)
    {
        while(left < right)
        {
            debug <<*left <<", " <<*right <<endl;
            swap(*left, *right);

            left++;
            right--;
        }
    }
};


int __tmain( )
{
    Solution solu;
    cout <<solu.ReverseSentence("student. a am I") <<endl;

    return 0;
}

使用STL的函数库来实现


也可以使用STL来实现这些功能

class Solution
{
public:

    string ReverseSentence(string str)
    {
        if (str.size( ) == 0)
        {
            return str;
        }

        reverse(str.begin(), str.end());

        size_t left = 0;
        size_t right = 0;
        while(right != string::npos)
        {
            left = str.find_first_not_of(' ', left);  //  第一个非空格字符是单词的起始位置
            right = str.find_first_of(' ', left);      //  第一个空格位置标识了单词的结束

            //  处理末尾是空格(原字符串开头是空格的情况)
            //  当最后全是空格的时候,此时可以结束循环
            if (left == string::npos)
            {
                break;
            }
            //  如果查找不到空格, 到了字符串的末尾
            //  此时[degin, str.size( )]是末尾的字符串
            if (right == string::npos)
            {
                reverse(str.begin( ) + left, str.end( ));
            }
            else        //  否则[left, end]是一个单词
            {
                reverse(str.begin( ) + left, str.begin() + right);
                left = right + 1;
            }
        }

        return str;
    }
};

用栈的后进先出特性实现翻转


当然由于栈是后进先出的,因此我们可以通过栈来实现翻转

  • 将每个字符依次入栈,那么出现的顺序正好就是逆序
//使用两个栈
class Solution
{
public:
    string ReverseSentence(string str)
    {
        if (str.size( ) == 0)
        {
            return str;
        }

        string          result;
        stack<char>     stk1;
        stack<char>     stk2;

        for (auto i : str)
        {   //把str中的全部压入
            debug <<"push in stack_1 "<<i <<endl;
            stk1.push(i);
        }

        //  通过将字符串压入栈中, 现在出栈顺序正好是入栈顺序的逆序
        //  即我们实现了一次整个字符串的翻转

        //  接下来我们翻转每个单词
        //  只要不是空格就一直入栈(实现翻转)
        //  遇见空格的时候,就读取栈中元素(出栈的顺序正好是每个单词的顺序)
        while (stk1.empty( ) != true)
        {
            if (stk1.top() != ' ')
            {   //没有遇到空格 就再弹出 压到第二个栈
                stk2.push(stk1.top());
                debug <<"pop stack_1, and push in stack_2 " <<stk1.top( ) <<endl;
                stk1.pop( );
            }
            else
            {   //如果遇到了空格 一个单词结束了  将第二个栈里的弹出
                while (stk2.empty( ) != true)
                {
                    result += stk2.top();

                    debug <<"pop form stack_2 " <<stk2.top( ) <<endl;
                    stk2.pop();
                }
                result += stk1.top();//空格也要加上
                stk1.pop();//不要忘记!!!
            }
        }
        while (!stk2.empty()) {//此时stk1已经空了 上面的循环进不去了 但是stk2中还有最后一个单词!!!!注意!!!
            result += stk2.top();
            stk2.pop();
        }
        return result;
    }
};

从后向前重新组装字符串


student. a am I

I am a student.

还有以一种思路就是从后向前,读取到每个单词,就开始顺序的拼接它们

class Solution
{
public:
    string ReverseSentence(string str)
    {
        string result;
        while (str.rfind(" ") != -1)
        {
            unsigned long position = str.rfind(" ");
            string temp = str.substr(position + 1);
            //debug <<temp <<endl;
            result = result + temp + ' ';
            str = str.substr(0, position);
            debug <<"str = " <<str <<endl;
        }
        //debug <<str <<endl;
        result = result + str;

        return result;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值