题目描述
思路解析动画文字版
关键不是背模板,而是看懂为什么这题适合单调栈 · 贪心。
1. 准备:栈空,k=3 待删:目标:从 1432219 里删 3 位让结果最小。用一个栈维护已保留的数字,越靠前越要小。当前栈空,k=3。
2. 读 1:栈空直接入栈:读到第 0 位 1,栈为空,没有可弹的更大数字,直接入栈。栈=[1],k 仍为 3。
3. 读 4:栈顶 1 不大于 4,入栈:读到第 1 位 4,栈顶 1 小于 4,不弹(删大数才划算)。直接入栈,栈=[1,4],k 仍为 3。
4. 读 3:栈顶 4 大于 3,触发弹出:读到第 2 位 3,栈顶是 4,4 大于 3。前面留着更大的 4 会让结果变大,且 k=3 还能删,应该弹出 4。
5. 弹出 4:k 由 3 减为 2:弹出栈顶 4,删数计数 k 由 3 减为 2。栈变回 [1],栈顶 1 不大于 3,停止弹出。
6. 入栈 3:把 3 入栈,栈=[1,3],k=2。比起之前的 [1,4],现在前缀更小了。
7. 读 2:栈顶 3 大于 2,弹出 3:读到第 3 位 2,栈顶 3 大于 2 且 k=2 还能删,弹出 3,k 由 2 减为 1。栈回到 [1],栈顶 1 不大于 2,停。
8. 入栈 2:把 2 入栈,栈=[1,2],k=1。还剩 1 个删除名额。
9. 读第二个 2:栈顶 2 不大于 2,入栈:读到第 4 位 2,栈顶 2 不大于 2(相等不删,删了也不会更小)。直接入栈,栈=[1,2,2],k 仍为 1。
10. 读 1:栈顶 2 大于 1,弹出 2:读到第 5 位 1,栈顶 2 大于 1 且 k=1 还能删,弹出一个 2,k 由 1 减为 0。栈变 [1,2],k 已用完。
11. k 已用完:1 直接入栈:k=0,没有删除名额了,即便栈顶 2 大于 1 也不能再弹。把 1 入栈,栈=[1,2,1]。
12. 读 9:k=0 不弹,直接入栈:读到第 6 位 9,k=0 无法删除,直接入栈。栈=[1,2,1,9],所有数字读完。
13. 读完检查:k=0,无需砍尾:遍历结束后若 k 还大于 0,要从栈尾再砍掉 k 位。本例 k=0,无需砍尾,栈保持 [1,2,1,9]。
14. 去前导零:把栈从底到顶拼成 1219,再去掉开头的 0。本例首位是 1 没有前导零,结果不变。
15. 输出结果 1219:栈底到顶 [1,2,1,9] 拼接得到 1219,即删 3 位后能得到的最小数字。若拼接为空则返回 0。
把这句话记住,下次遇到同类题,就能更快选出方向。
参考代码
class Solution: def removeKdigits(self, num, k): st = [] for ch in num: while k and st and st[-1] > ch: st.pop() k -= 1 st.append(ch) if k: st = st[:-k] ans = ''.join(st).lstrip('0') return ans or '0'复杂度
- 时间复杂度:O(n),每个数字最多入栈一次、出栈一次,总操作数与 num 长度成正比
- 空间复杂度:O(n),栈最多保存全部 n 个数字
可套用的代码模板
模板不是死背,而是提醒你写代码前先把状态、转移和边界排好。
Python
# 单调栈 · 贪心 通用检查表# 1. 定义状态/指针/容器# 2. 每轮只做一个清晰动作# 3. 更新答案并处理边界易错点
这道题到这就讲完了。动画和文字是同一套思路——别光看,关掉页面自己默写一遍。然后顺着主线继续:
每日温度
LeetCode 739 · 中等 · 沿着 栈套路 继续往下推进
把这道题真正学会,再走
图解算法年卡 ¥99 /年
- ✓本题每步动画的吴师兄语音讲解(全站陆续覆盖)
- ✓小欧带 8 步通关训练——追问到不看答案也能写对、能 30 秒讲给面试官听
- ✓学习报告,记录每道题的掌握程度
76k+ GitHub Star · 吴师兄开源图解算法,几十万开发者在看的算法讲解
想成体系刷透这类套路?去图解算法专题