题意
给你一个字符串 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;
}
};
致谢
感谢灵神的题解使我豁然开朗。
210

被折叠的 条评论
为什么被折叠?



