重新排列句子中的单词

题目描述

「句子」是一个用空格分隔单词的字符串。给你一个满足下述格式的句子 text :

句子的首字母大写
text 中的每个单词都用单个空格分隔。
请你重新排列 text 中的单词,使所有单词按其长度的升序排列。如果两个单词的长度相同,则保留其在原句子中的相对顺序。

请同样按上述格式返回新的句子。

示例 1:

输入:text = "Leetcode is cool"
输出:"Is cool leetcode"
解释:句子中共有 3 个单词,长度为 8 的 "Leetcode" ,长度为 2 的 "is" 以及长度为 4 的 "cool" 。
输出需要按单词的长度升序排列,新句子中的第一个单词首字母需要大写。
示例 2:

输入:text = "Keep calm and code on"
输出:"On and keep calm code"
解释:输出的排序情况如下:
"On" 2 个字母。
"and" 3 个字母。
"keep" 4 个字母,因为存在长度相同的其他单词,所以它们之间需要保留在原句子中的相对顺序。
"calm" 4 个字母。
"code" 4 个字母。
示例 3:

输入:text = "To be or not to be"
输出:"To be or to be not"

题目分析

这道题目是力扣上的一道原题,看似不复杂,(难度为中等),但其实里面有许多细节是需要注意的。就比如说它的要求,要排完之后首字母大写,按照单词长度升序排列,而且原先单词长度相等的,排完之后相对位置不能改变。针对这道题,我足足花了将近两个小时才把要求的功能完全实现,在VS上是可以的,但是在力扣上就超时了,很难受,主要还是我用了冒泡的缘故。以下是我的思路,当做反面典型吧。

(1)首先创建一个vector容器,把句子划分为单词,装到容器中,这里要注意,装的过程中,顺便给每一个单词后缀都加一个空格" ",以便于之后重建句子。

(2)之后对于容器中的单词,用了最简单的冒泡排序把单词长度由小到大排了一下,(这就是超时的原因);

(3)再用一个堆栈把容器中的单词依次压栈;

(4)最后用一个字符串去接受栈中的单词。

总体来说,代码整体过于繁杂,而且冒泡排序绝对不会用在这种算法题中的,是我太天真了,以为不会超时!!!

 

class Solution {
public:
    string arrangeWords(string& text) {

        //把text分开加入v中
        vector<string> v;

        string v_sub;
        for (int i = 0; i < text.size(); i++)
        {
            if (text[i] != ' ')
            {
                if (text[i] < 97)
                {
                    text[i] += 32;
                }
                v_sub += text[i];

                if (i == text.size() - 1)
                {
                    v_sub += " ";
                    v.push_back(v_sub);
                }

            }
            else
            {
                v_sub += " ";
                v.push_back(v_sub);
                v_sub = "";
            }

        }



        string return_string;
        stack<string> sta;
        int return_string_sz = v.size() - 1;
        for (int m = 0; m < v.size(); m++)
        {
            for (int n = 0; n < v.size() - m-1; n++)
            {
                if (v[n].size() > v[n + 1].size())
                {
                    string temp;
                    temp = v[n];
                    v[n] = v[n + 1];
                    v[n + 1] = temp;

                }

            }
            sta.push(v[return_string_sz--]);
        }
        int sta_sz = sta.size();
        for (int i = 0; i < sta_sz; i++)
        {
            return_string += sta.top();
            sta.pop();

        }
        return_string[0] -= 32;
        return_string.pop_back();
        return return_string;


    }
};

 下面言归正传,还是来看一看大佬怎么做的吧,以下代码摘自力扣大佬题解。

//stable_sort: 132ms -> 76ms
class Solution {
public:
    string arrangeWords(string text) {
        int index = 0, t_len = text.size();
        text[0] -= ('A' - 'a');
        vector<pair<int,int>> res;
        for(int i = 0; i <= t_len; i++) {
            if(i == t_len || text[i] == ' ') {  
                //res.push_back(make_pair(index, i - index));
                res.emplace_back(index, i - index);
                index = i + 1;
            }
        }
        //之前使用的sort,主要是不知道有stable_sort这一说
        stable_sort(res.begin(), res.end(), [](const auto& a, const auto& b) {
            return a.second < b.second;
        });
        string ans;
        ans.reserve(t_len + 1);
        for(const pair<int,int>& p: res) {
            //ans += text.substr(p.first, p.second) + " ";
            ans.append(text, p.first, p.second).push_back(' ');
        }
        ans[0] += ('A' - 'a');
        ans.pop_back();
        return ans;
    }
};

看了这段代码,只能感叹妙不可言。

它用容器res去维护了一组包含两个整数的pair<int,int>,其中第一个int表示单词在句子中的起始索引,第二个表示单词的长度。

这里面用到了容器的emplace_back()方法。

这样以来,就得到了装有很多pair的容器,里面每个pair都存储了单词的起始索引和长度,这个时候再按照长度进行排序就OK了,所以对sort进行重载,实现对pair里面的second进行排序。

stable_sort(res.begin(), res.end(), [](const auto& a, const auto& b) {
            return a.second < b.second;
        });

这里使用到了lambda函数(学以致用)。

最后,再用一个空的字符串依次去接收,这里用到了append(),里面有三个参数,这里第一个代表源字符串,第二个为起始位置,第三个为长度,起始就是往一个字符串里面去添加一个字符串,只不过是你可以指定长度、起始位置。

最后是运行结果

输入 “Keep calm and code on”

输出:"On and keep calm code"

没毛病,老铁。

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值