题目描述
思路解析动画文字版
随便从中间开组可能占掉小牌,导致前面无法成组。
每次从当前最小还剩牌 x 开始,扣 x,x+1,... 这组连续牌。
① 排序后,从「还剩的最小牌」起贪心:先数清每张牌几张;之后每次都拿最小的牌开一组。
② 最小是 1 → 连出 [1,2,3]:最小牌没有退路,只能领一组;连号的 2、3 被一起带走。
③ 再取最小 2 → 连出 [2,3,4]:重复同一招:永远从剩下的最小牌开组。
④ 最后取 6 → 连出 [6,7,8]:最后三张刚好成一组。
⑤ 全部成组 → 返回 true:每张牌都用光且都在连号组里 → 成功。
一句话记住:每次从当前最小还剩牌 x 开始,扣 x,x+1,... 这组连续牌。
边界三连:本题真边界:不整除、groupSize=1、连号断档。
雷区实演 · 为什么必须从最小牌开组:换个开组顺序就翻车:最小牌必须最先被消化。
面试追问 · 贪心正确性:每次从当前最小还剩牌 x 开始,扣 x,x+1,... 这组连续牌。
面试追问 · 为何用计数:面试追复杂度时,不要只报 O,要把“每个元素进出几次”讲清楚。
面试追问 · 取最小的实现:一手顺子 不是孤题,它练的是 贪心 的状态设计。
这题学完不要乱跳,下一步去对应专题 /leetcode-animation/ds?k=greedy 连刷同类题;卡住时用 AI 答疑问“我的状态定义哪里不稳”。
参考代码
class Solution: def isNStraightHand(self, hand, groupSize): if len(hand) % groupSize: return False from collections import Counter cnt = Counter(hand) for x in sorted(cnt): need = cnt[x] if need > 0: for y in range(x, x + groupSize): if cnt[y] < need: return False cnt[y] -= need return True复杂度
- 时间复杂度:O(n log n),排序(或用有序结构取最小)主导;之后每张牌被消费一次
- 空间复杂度:O(n),计数表 Counter 最多存 n 张牌的频次
可套用的代码模板
记牢:不整除先 false → 从最小点数开组 → 连 groupSize 张各扣 need → 中途不够即 false。
Python
# 连号分组 / 一手顺子 · 贪心骨架if len(hand) % groupSize: return False # 不整除先剪枝cnt = Counter(hand)for x in sorted(cnt): # 从最小点数开始 need = cnt[x] if need == 0: continue for y in range(x, x + groupSize): # 连出一组 x..x+groupSize-1 if cnt[y] < need: return False # 某张不够 → 失败 cnt[y] -= needreturn True易错点
面试追问把动画讲成自己的话
追问这题的贪心为什么是对的(正确性)?
这道题到这就讲完了。动画和文字是同一套思路——别光看,关掉页面自己默写一遍。然后顺着主线继续:
合并三元组以形成目标三元组
LeetCode 1899 · 中等 · 沿着 贪心 继续往下推进
把这道题真正学会,再走
图解算法年卡 ¥99 /年
- ✓本题每步动画的吴师兄语音讲解(全站陆续覆盖)
- ✓小欧带 8 步通关训练——追问到不看答案也能写对、能 30 秒讲给面试官听
- ✓学习报告,记录每道题的掌握程度
76k+ GitHub Star · 吴师兄开源图解算法,几十万开发者在看的算法讲解
想成体系刷透这类套路?去图解算法专题