1958. 检查操作是否合法

判断好线段的合法涂色操作 —— LeetCode 相关题目解析


题目描述

给定一个 8x8 的棋盘 board,每个格子有三种可能的状态:

  • '.' 表示空格
  • 'W' 表示白色格子
  • 'B' 表示黑色格子

现在你要对一个空格 (rMove, cMove) 进行涂色操作,颜色为 color(白色 'W' 或黑色 'B')。涂色操作的合法性判断规则是:

  • 涂色后,(rMove, cMove) 这个格子必须是 “好线段” 的一个端点。

“好线段” 定义如下:

  • 线段是棋盘上连续的一条直线,可以是水平方向、垂直方向或对角线方向。
  • 线段长度必须至少为3格。
  • 线段两端格子的颜色相同,且与涂色的颜色相同。
  • 线段中间所有格子的颜色都相同,且是与端点颜色不同的另一种颜色。
  • 线段中不能有空格。

简言之,这相当于反转棋类游戏中一条“夹击”的规则:新涂色位置必须和已有颜色形成“端点”,并且中间夹着连续的对手颜色。


解题分析

本题关键点在于判断,以待涂色点 (rMove, cMove) 作为端点,是否存在符合规则的“好线段”。

核心逻辑:

  • 检查所有8个方向(水平、垂直、两条对角线的正反两个方向):
    • 第一个格子必须是对手颜色(opponent)。
    • 中间所有格子必须连续且均为对手颜色。
    • 线段末尾格子必须为当前涂色颜色。
    • 线段长度至少为3格(包含两端点和中间对手颜色格子)。
  • 只要有一个方向满足,操作即合法。

解题方法

纯逻辑判断 + 8方向遍历

这种方案不修改棋盘原状态,通过逻辑推断判断合法性。

核心步骤:

  1. 定义8个方向向量:
directions = [
    (0, 1),  (0, -1),
    (1, 0),  (-1, 0),
    (1, 1),  (1, -1),
    (-1, 1), (-1, -1)
]
  1. 遍历所有方向,对于每个方向:
    • (rMove, cMove) 移动到下一个格子 (r, c)
    • 若越界或该格为空或颜色与涂色颜色相同,跳过该方向。
    • 记对手颜色为 board[r][c]
    • 沿该方向继续移动,直到遇到非对手颜色或越界。
    • 若末尾格子颜色是涂色颜色,且线段长度≥3,返回 True
  2. 若所有方向都不满足条件,返回 False

代码实现

class Solution:
    def checkMove(self, board: List[List[str]], rMove: int, cMove: int, color: str) -> bool:
        directions = [
            (0, 1),  (0, -1),
            (1, 0),  (-1, 0),
            (1, 1),  (1, -1),
            (-1, 1), (-1, -1)
        ]
        
        def in_board(r, c):
            return 0 <= r < 8 and 0 <= c < 8
        
        for dr, dc in directions:
            r, c = rMove + dr, cMove + dc
            
            # 第一个格子必须是对手颜色
            if not in_board(r, c) or board[r][c] == '.' or board[r][c] == color:
                continue
            
            opponent = board[r][c]
            length = 2  # 包含端点和第一个对手格
            
            r += dr
            c += dc
            
            while in_board(r, c) and board[r][c] == opponent:
                length += 1
                r += dr
                c += dc
            
            # 检查末尾是否为当前颜色,且长度≥3
            if length >= 3 and in_board(r, c) and board[r][c] == color:
                return True
        
        return False

示例说明

示例1:

board = [
    [".", ".", ".", "B", ".", ".", ".", "."],
    [".", ".", ".", "W", ".", ".", ".", "."],
    [".", ".", ".", "W", ".", ".", ".", "."],
    [".", ".", ".", "W", ".", ".", ".", "."],
    ["W", "B", "B", ".", "W", "W", "W", "B"],
    [".", ".", ".", "B", ".", ".", ".", "."],
    [".", ".", ".", "B", ".", ".", ".", "."],
    [".", ".", ".", "W", ".", ".", ".", "."]
]
rMove, cMove, color = 4, 3, "B"
  • 涂色点 (4,3) 为空格,涂为 'B' 后,沿竖直方向向上找:
    • 第一个格子是 'W'(对手颜色)
    • 中间连续对手颜色 'W' 格子 (3,3), (2,3), (1,3)
    • 末尾格子是 'B'(涂色颜色)
  • 满足“好线段”定义,返回 True

示例2:

board = [
    [".", ".", ".", ".", ".", ".", ".", "."],
    [".", "B", ".", ".", "W", ".", ".", "."],
    [".", ".", "W", ".", ".", ".", ".", "."],
    [".", ".", ".", "W", "B", ".", ".", "."],
    [".", ".", ".", ".", ".", ".", ".", "."],
    [".", ".", ".", ".", "B", "W", ".", "."],
    [".", ".", ".", ".", ".", ".", "W", "."],
    [".", ".", ".", ".", ".", ".", ".", "B"]
]
rMove, cMove, color = 4, 4, "W"
  • 涂色点 (4,4) 虽然会产生好线段,但该点处于线段中间,不是端点。
  • 不满足“涂色点必须是端点”的条件,返回 False

总结

  • 本题考察了二维棋盘上的方向遍历与颜色连续性判断。
  • 纯逻辑8方向判断方案不修改棋盘,更安全,易于理解。
  • 通过检查涂色点在各方向的邻接格颜色组合,判定是否形成满足条件的“好线段”。
  • 算法时间复杂度为常数(固定8x8棋盘及8方向),效率足够。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值