Leetcode每日一题打卡 2434

题意

        给你一个字符串 s 和一个机器人,机器人当前有一个空字符串 t 。执行以下操作之一,直到 s 和 t 都变成空字符串:

  • 删除字符串 s 的 第一个 字符,并将该字符给机器人。机器人把这个字符添加到 t 的尾部。
  • 删除字符串 t 的 最后一个 字符,并将该字符给机器人。机器人将该字符写到纸上。

        请你返回纸上能写出的字典序最小的字符串。

思考

        题目中的第一个、最后一个、尾部是关键词,本题照着几个样例写了写,大致能想出是使用的主要数据结构是栈。把“t”当做一个栈来使用,“纸”就是栈的输出。难点在于什么时候让栈里的元素出栈。博主看了三个样例半天,能反应过来是贪心的想法,如果后面的字母字典序比前面的小,就不出栈,大了则需要出栈。但这个想法测试了几个用例发现不对,经常会出现错误。想法应该是对的,但需要改进。

题解——灵茶山艾府

       根据题意,t 中字符是先进后出的,是一个栈。问题相当于从左到右遍历 s,在允许用一个辅助栈的前提下,计算能得到的字典序最小的字符串。

       看示例 2,s=bac:s[0]=b 入栈,能立刻出栈吗?如果立刻出栈,那么答案的第一个字母是 b。如果不出栈,后面遍历到 a 的时候把 a 出栈,那么答案的第一个字母就会是 a,字典序更小。因此,如果我们发现后面有更小的字母,那就不出栈。
        s[1]=a 入栈,能立刻出栈吗?如果立刻出栈,那么答案的第一个字母是 a。如果不出栈,后面也没有更小的字母了。把 c 入栈再出栈,答案的第一个字母是 c,不是最优的。因此,如果我们发现当前字母比剩余字母(后缀 s[i+1:])中的最小值还小,那么就立刻出栈。
        此外,a出栈后,应该继续把栈顶的 b 也出栈,不然后面 c 入栈出栈,会把 c 填到答案的第二个位置上,不是最优的。s[2]=c 入栈,再出栈。最终答案为 abc。
        如果 s 中有相同字母,要如何处理呢?以 s=caba 为例。对于 s[1]=a,应该立刻出栈。如果不出栈,遍历到 s[3]=a 才出栈,那么结果是 abac,但正确答案是 aabc。在错误答案中,因为没有及时把 a 出栈,我们把更大的 b 插在了两个 a 中间。所以如果栈顶等于剩余字母(后缀 s[i+1:])中的最小值,也应该立刻出栈。

        总结:如果栈顶 ≤ 剩余字母(后缀 s[i+1:])中的最小值,就立刻出栈。

Leetcode 2434解题代码

class Solution {
public:
    string robotWithString(string s) 
    {
        int n = s.size();
        vector<char> after(n + 1);  // 计算后续最小值
        after[n] = 'z';  //置为最大值,方便取min
        for (int i = n - 1; i >= 0; i--) 
        {
            after[i] = min(after[i + 1], s[i]);
        }
        string result;
        stack<char> st;
        for (int i = 0; i < n; i++) 
        {
            st.push(s[i]);
            while (!st.empty() && st.top() <= after[i + 1]) 
            {
                result += st.top();
                st.pop();
            }
        }
        return result;
    }
};

致谢

        感谢灵神的题解使我豁然开朗。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值