SWE · Screen Coding

Snowflake LC794 扩展线索:先验证标准井字棋状态可达性

Phone Coding 题目只说 LC794 的扩展版;本文明确只解标准 3×3 轮流落子、胜后即停的状态校验,扩展规则列入待核。

题目重点:Phone Coding 题目只说 LC794 的扩展版;本文明确只解标准 3×3 轮流落子、胜后即停的状态校验,扩展规则列入待核。

题意与假设

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

  • 训练版为标准 3×3 棋盘,X 先手、X/O 轮流每次落一格;已有玩家胜利时立即停止,不能继续落子。
  • 输入是三行长度 3 的字符串,仅允许 X、O、空格;返回布尔值,不负责给出具体落子序列。扩展版可能不满足这些规则,需另核原题。

解题路线

  1. 先检查棋盘形状和字符集合;数 X/O,合法轮次只能 X=O 或 X=O+1。
  2. 检查 8 条获胜线,X 与 O 不能同时获胜;若 X 获胜必须 X=O+1,若 O 获胜必须 X=O。
  3. 这些条件对标准规则也是充分的:合法轮次和赢家最后一步可构造一条未提前结束的落子序列;若担心证明,训练测试用完整状态图枚举佐证。
  4. 从空棋盘 BFS 生成所有合法落子状态,赢家出现即停止;把 3^9=19,683 种板面全部与条件判断对照,得到 5,478 个可达状态。

手动走一遍

['XXX','OO ',' '] 有 X=3/O=2 且 X 胜,合法;['XXX','OOO',' '] 双方同时胜,非法;['XXX','OO ',' O'] 有 X=3/O=3,轮次计数本身允许,但 X 获胜不可能是 O 刚下完的状态,也非法。

Python 参考实现

下面的代码按上文假设实现,适合本地运行并追加自己的测试用例。

代码区可横向滚动;使用键盘时,先聚焦代码区再按方向键查看。

"""Validate standard 3x3 Tic-Tac-Toe states; source extension unspecified."""


LINES = ((0, 1, 2), (3, 4, 5), (6, 7, 8),
         (0, 3, 6), (1, 4, 7), (2, 5, 8),
         (0, 4, 8), (2, 4, 6))


def valid_state(rows: list[str]) -> bool:
    if len(rows) != 3 or any(len(row) != 3 for row in rows):
        return False
    board = "".join(rows)
    if any(cell not in "XO " for cell in board):
        return False
    x = board.count("X")
    o = board.count("O")
    if x != o and x != o + 1:
        return False
    x_win = any(all(board[i] == "X" for i in line) for line in LINES)
    o_win = any(all(board[i] == "O" for i in line) for line in LINES)
    if x_win and o_win:
        return False
    if x_win and x != o + 1:
        return False
    if o_win and x != o:
        return False
    return True

复杂度

固定 3×3 棋盘只检查 9 格和 8 条胜利线,为 O(1) 时间/空间;若扩展到 N×N 与 K 连线,胜线枚举和轮次充分性都需重推,不能直接照搬常数复杂度。

易错点与追问

容易失分的边界

  • 只检查 X/O 数量,漏掉双赢或赢家与落子数不符。
  • 允许胜利后继续落子。
  • 把一篇只说 LC794 扩展版的题目写成完整扩展规则。
  • 把标准 3×3 的充分条件未经证明套到任意大棋盘与胜利长度。

继续深挖

  • 若棋盘改成 N×N、连 K 获胜,如何判定状态可达?
  • 若要返回一条合法落子序列,需做回溯还是可构造?
  • 如果允许胜后继续落子,上述条件哪些会改变?
  • 题目所说扩展到底是规则、尺寸还是输出形式?
✓已复制微信号!