2434. 使用机器人打印字典序最小的字符串
题目描述
给了一个初始字符串s,一个机器人,并且机器人当前有一个字符串t。
可以有两个操作:
- 删除s的第一个字符,添加到t的结尾
- 删除t的最后一个字符,将字符写到纸上
问纸上能获取到字典序最小的字符串?
基本分析
- 两个操作对应的是什么? 将t看做一个栈,操作1代表入栈,操作2对应出栈
- 直观上感觉使用贪心来做,但需要考虑怎么贪?
- 只考虑前后两个字符的关系行不行?简单分析是不行的。例如bca,c比b大,单纯考虑两个关系,b就应该出栈了,而最优的解是b入,c入,a入。
- 所以需要考虑全局的最小情况,如果全局存在多个最小怎么考虑?加入是bcaada,bca先入,第一个a=后续的最小a,此刻这个a是需要弹出还是继续入队?明显是应该弹出此时栈中是bcd,弹出了3个a,最终结果是aaadcb。
- 现在问题是怎么能知道剩余的全局最小的情况,这个全局最小是变化的?能想到用Counter去统计,然后遍历到一个字符就维护cnt一次。注意可能存在-1后为0的情况,这个时候怎么办?利用一个while取找满足条件的(个数不为0或者只有最大时会退出while)
- 有一个细节是,一个字符c入栈以后,出栈怎么考虑,最多是这个字符出吗?答案是只要栈不空并且栈顶元素<=min对应的字符,就应该一直出,这里也是用while实现
代码
栈-哈希表维护剩余最小值-贪心出栈
class Solution: def robotWithString(self, s: str) -> str: ans = [] st = [] cnt = Counter(s) min_ = 0 for c in s: cnt[c] -= 1 while min_ < 25 and cnt[ascii_lowercase[min_]] == 0: min_ += 1 st.append(c) while st and st[-1] <= ascii_lowercase[min_]: ans.append(st.pop()) return "".join(ans)
复杂度
时间:n为s长度,是字符集大小,这里是26。每个字符入队出队最多一次,且min只增不减少,最终复杂度为
空间:最差情况下需要n的栈空间,所以是
总结
- 能看出来两个操作和栈的关系
- 能看出来用贪心,但是贪心的细节需要考虑清楚。(1)需要剩余的全局min,而不是相邻的大小关系;(2)全局min需要用哈希表存,用while去维护,每-1后进行更新,拿到合适的值;(3)出栈的时候可能是出0出1出多,取决于栈顶和min的关系,这个也是用while去实现
- python给了一个列表ascii_lowercase,可以通过索引取出对应小写字母
- 结果用列表去存,最后生成字符串
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现