题目描述
思路解析动画文字版
记住这套「从大到小、先把队尾挪回队首撤销轮转、再把当前牌压入队首」,后面每一帧都在套它。
先看手里有哪些牌。输入顺序其实无所谓,因为题目允许我们任意重排,真正决定答案的只是这些值和张数。
把牌排好序,这一排就是我们希望被「依次亮出」的递增顺序。但注意:这不是牌堆的摆放,而是亮出的先后。难点正是把它倒推回摆放。
从最大的牌开始。队列还空着,直接把 21 放进去(绿色)。它是最后才会被亮出的牌,所以最先入列。
准备放入 13 之前,按套路要先把队尾挪回队首。可现在队列只有一张 21,挪过来还是它,走个流程即可,下一帧再压入 13。
把当前这张 13 压到队首(绿色)。它比已在队列里的都小,会比它们更早被亮出,所以排在更靠前的位置。
准备放入 8 之前,先撤销上一轮「把顶牌移到底部」:把队尾的 21 挪回队首(红色那张)。这一步保证倒放后队列能还原。
把当前这张 8 压到队首(绿色)。它比已在队列里的都小,会比它们更早被亮出,所以排在更靠前的位置。
准备放入 5 之前,先撤销上一轮「把顶牌移到底部」:把队尾的 13 挪回队首(红色那张)。这一步保证倒放后队列能还原。
把当前这张 5 压到队首(绿色)。它比已在队列里的都小,会比它们更早被亮出,所以排在更靠前的位置。
准备放入 3 之前,先撤销上一轮「把顶牌移到底部」:把队尾的 21 挪回队首(红色那张)。这一步保证倒放后队列能还原。
把当前这张 3 压到队首(绿色)。它比已在队列里的都小,会比它们更早被亮出,所以排在更靠前的位置。
准备放入 2 之前,先撤销上一轮「把顶牌移到底部」:把队尾的 8 挪回队首(红色那张)。这一步保证倒放后队列能还原。
把当前这张 2 压到队首(绿色)。它比已在队列里的都小,会比它们更早被亮出,所以排在更靠前的位置。
六张牌从大到小全部放完,队列从队首到队尾就是要求的牌堆摆放:[2, 8, 3, 21, 5, 13]。下面正着走一遍,验证它亮出来确实递增。
亮出当前牌堆顶部的 2(绿色),记到「已亮出」里。到目前为止亮出的序列是 2,一直在变大。
按规则,把新的顶牌 8 移到牌堆底部(红色那张到了队尾),轮到它后面的牌当顶。剩下的牌堆是 [3, 21, 5, 13, 8]。
亮出当前牌堆顶部的 3(绿色),记到「已亮出」里。到目前为止亮出的序列是 2、3,一直在变大。
按规则,把新的顶牌 21 移到牌堆底部(红色那张到了队尾),轮到它后面的牌当顶。剩下的牌堆是 [5, 13, 8, 21]。
亮出当前牌堆顶部的 5(绿色),记到「已亮出」里。到目前为止亮出的序列是 2、3、5,一直在变大。
按规则,把新的顶牌 13 移到牌堆底部(红色那张到了队尾),轮到它后面的牌当顶。剩下的牌堆是 [8, 21, 13]。
亮出当前牌堆顶部的 8(绿色),记到「已亮出」里。到目前为止亮出的序列是 2、3、5、8,一直在变大。
按规则,把新的顶牌 21 移到牌堆底部(红色那张到了队尾),轮到它后面的牌当顶。剩下的牌堆是 [13, 21]。
亮出当前牌堆顶部的 13(绿色),记到「已亮出」里。到目前为止亮出的序列是 2、3、5、8、13,一直在变大。
按规则,把新的顶牌 21 移到牌堆底部(红色那张到了队尾),轮到它后面的牌当顶。剩下的牌堆是 [21]。
亮出当前牌堆顶部的 21(绿色),记到「已亮出」里。到目前为止亮出的序列是 2、3、5、8、13、21,一直在变大。
回放结束,亮出的顺序正好是 2、3、5、8、13、21,一路严格递增。这证明刚才逆向推出的摆放 [2, 8, 3, 21, 5, 13] 完全正确。
边界先想清:单张直接返回、两张手推一遍、答案只取决于有哪些值和几张。
面试重点:讲清「倒放时间轴」的还原逻辑,并知道正向下标模拟是等价替代。
参考代码
from __future__ import annotationsfrom typing import *from collections import *from functools import *from itertools import *from math import *from heapq import *from bisect import *class Solution: def deckRevealedIncreasing(self, deck: List[int]) -> List[int]: q = deque() for v in sorted(deck, reverse=True): if q: q.appendleft(q.pop()) q.appendleft(v) return list(q)复杂度
- 时间:O(n log n),排序主导;之后每张牌的轮转+入列都是 O(1),模拟共 O(n)
- 空间:O(n),一个双端队列存所有牌;排序栈开销 C++/Java O(log n)、Python 最坏 O(n)
易错点
面试追问把动画讲成自己的话
追问为什么逆向能精确还原摆放?
追问能不能不逆向,用下标正向模拟?
这道题到这就讲完了。动画和文字是同一套思路——别光看,关掉页面自己默写一遍。然后顺着主线继续:
最大宽度坡
LeetCode 962 · 中等 · 沿着 栈套路 继续往下推进
把这道题真正学会,再走
图解算法年卡 ¥99 /年
- ✓本题每步动画的吴师兄语音讲解(全站陆续覆盖)
- ✓小欧带 8 步通关训练——追问到不看答案也能写对、能 30 秒讲给面试官听
- ✓学习报告,记录每道题的掌握程度
76k+ GitHub Star · 吴师兄开源图解算法,几十万开发者在看的算法讲解
想成体系刷透这类套路?去图解算法专题