判断好线段的合法涂色操作 —— LeetCode 相关题目解析
题目描述
给定一个 8x8 的棋盘 board
,每个格子有三种可能的状态:
'.'
表示空格'W'
表示白色格子'B'
表示黑色格子
现在你要对一个空格 (rMove, cMove)
进行涂色操作,颜色为 color
(白色 'W'
或黑色 'B'
)。涂色操作的合法性判断规则是:
- 涂色后,
(rMove, cMove)
这个格子必须是 “好线段” 的一个端点。
“好线段” 定义如下:
- 线段是棋盘上连续的一条直线,可以是水平方向、垂直方向或对角线方向。
- 线段长度必须至少为3格。
- 线段两端格子的颜色相同,且与涂色的颜色相同。
- 线段中间所有格子的颜色都相同,且是与端点颜色不同的另一种颜色。
- 线段中不能有空格。
简言之,这相当于反转棋类游戏中一条“夹击”的规则:新涂色位置必须和已有颜色形成“端点”,并且中间夹着连续的对手颜色。
解题分析
本题关键点在于判断,以待涂色点 (rMove, cMove)
作为端点,是否存在符合规则的“好线段”。
核心逻辑:
- 检查所有8个方向(水平、垂直、两条对角线的正反两个方向):
- 第一个格子必须是对手颜色(
opponent
)。 - 中间所有格子必须连续且均为对手颜色。
- 线段末尾格子必须为当前涂色颜色。
- 线段长度至少为3格(包含两端点和中间对手颜色格子)。
- 第一个格子必须是对手颜色(
- 只要有一个方向满足,操作即合法。
解题方法
纯逻辑判断 + 8方向遍历
这种方案不修改棋盘原状态,通过逻辑推断判断合法性。
核心步骤:
- 定义8个方向向量:
directions = [
(0, 1), (0, -1),
(1, 0), (-1, 0),
(1, 1), (1, -1),
(-1, 1), (-1, -1)
]
- 遍历所有方向,对于每个方向:
- 从
(rMove, cMove)
移动到下一个格子(r, c)
。 - 若越界或该格为空或颜色与涂色颜色相同,跳过该方向。
- 记对手颜色为
board[r][c]
。 - 沿该方向继续移动,直到遇到非对手颜色或越界。
- 若末尾格子颜色是涂色颜色,且线段长度≥3,返回
True
。
- 从
- 若所有方向都不满足条件,返回
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方向),效率足够。