OCI IC4 · Phone Coding

Oracle LC 846 无重复数字变体:连续牌组如何切分

从 Oracle IC4 题目的无重复数字约束出发,证明排序后连续分组的充分必要性,并核对空输入与重复值。

题目重点:从 Oracle IC4 题目的无重复数字约束出发,证明排序后连续分组的充分必要性,并核对空输入与重复值。

题意与假设

这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。

  • 牌值互不相同,每组恰好 group_size 张且组内数值连续;group_size 必须为正。
  • 训练版把空手牌视为可切成零组;若传入重复值则拒绝,因为这超出了题目明确的变体约束。

解题路线

  1. 先检查总张数可被组大小整除,再排序。
  2. 从最小未使用值开始,它只能是某一组的最小值;在无重复条件下,其后 group_size−1 个相邻数必须依次加一。
  3. 每次消耗排序结果的一个连续块;若任意块内出现断点就返回 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) 额外数组。

易错点与追问

容易失分的边界

  • 把无重复变体的排序分块结论直接用于含重复的原版。
  • 只检查组内差值而忘记总张数整除。
  • 没有先说明空手牌和非法组大小的约定。

继续深挖

  • 允许重复牌值时,如何用最小剩余牌和频次表构造组?
  • 牌值是很大的整数或可能溢出时,连续比较怎样写?
✓已复制微信号!