题目重点:从 Oracle IC4 题目的无重复数字约束出发,证明排序后连续分组的充分必要性,并核对空输入与重复值。
题意与假设
这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。
- 牌值互不相同,每组恰好 group_size 张且组内数值连续;group_size 必须为正。
- 训练版把空手牌视为可切成零组;若传入重复值则拒绝,因为这超出了题目明确的变体约束。
解题路线
- 先检查总张数可被组大小整除,再排序。
- 从最小未使用值开始,它只能是某一组的最小值;在无重复条件下,其后 group_size−1 个相邻数必须依次加一。
- 每次消耗排序结果的一个连续块;若任意块内出现断点就返回 false。对一般 LC 846 含重复值输入,应改用频次计数,不能直接套用本实现。
手动走一遍
[7,3,4,6,5,2]、group_size=3 排序为 [2,3,4,5,6,7],拆成 [2,3,4] 和 [5,6,7];[1,2,4,5]、group_size=2 第二组从 4 开始,仍可行;[1,2,4,6] 则第二组断开。
Python 参考实现
下面的代码按上文假设实现,适合本地运行并追加自己的测试用例。
代码区可横向滚动;使用键盘时,先聚焦代码区再按方向键查看。
"""LC 846 training variant with all card values distinct."""
def can_partition_unique_hand(cards: list[int], group_size: int) -> bool:
if group_size <= 0:
raise ValueError("group_size must be positive")
if len(cards) % group_size:
return False
if len(set(cards)) != len(cards):
raise ValueError("training variant requires distinct card values")
ordered = sorted(cards)
for start in range(0, len(ordered), group_size):
for index in range(start + 1, start + group_size):
if ordered[index] != ordered[index - 1] + 1:
return False
return True
复杂度
排序 O(N log N),逐块扫描 O(N),额外排序空间依语言实现而定;展示的 Python sorted 使用 O(N) 额外数组。
易错点与追问
容易失分的边界
- 把无重复变体的排序分块结论直接用于含重复的原版。
- 只检查组内差值而忘记总张数整除。
- 没有先说明空手牌和非法组大小的约定。
继续深挖
- 允许重复牌值时,如何用最小剩余牌和频次表构造组?
- 牌值是很大的整数或可能溢出时,连续比较怎样写?
