Codefights扫雷(minesweeper)Python代码问题:边界雷统计失效求助
扫雷代码问题分析与优化方案
问题原因拆解
你遇到的问题主要有三个核心点:
- 循环行/列逻辑搞反:你写的遍历循环把行和列的逻辑完全弄混了!
for i in range(0, len(matrix[0])-1)里的len(matrix[0])是矩阵的列数,你用它来控制行索引的范围,而j反而用行数来限制。这直接导致测试用例里最后一列的雷根本没被遍历到,自然不会触发周围单元格的计数操作,结果全为0也就不奇怪了。 - 边界补全不完整:你只给每行开头插入了边界标记
"x",但注释掉了结尾插入边界的代码,就算循环逻辑对了,处理最后一列的雷时,右侧的计数操作也会触发索引越界错误。 - 输出矩阵处理跟着出错:因为前面的遍历逻辑错误,后续对输出矩阵的裁剪操作也无法得到正确结果。
更简洁的优化实现
其实不用额外添加边界,我们可以直接通过判断相邻位置的有效性来避免索引问题,同时保证遍历逻辑正确。这里提供两种思路的实现:
思路1:遍历每个单元格,统计周围雷的数量
def minesweeper(matrix): rows = len(matrix) cols = len(matrix[0]) if rows > 0 else 0 # 初始化结果矩阵,所有位置先设为0 result = [[0 for _ in range(cols)] for _ in range(rows)] # 逐个遍历原矩阵的每个单元格 for i in range(rows): for j in range(cols): # 如果当前单元格是雷,跳过(我们只需要计算非雷位置的周围雷数) if matrix[i][j]: continue # 统计周围8个方向的雷数 mine_count = 0 # 遍历8个方向的偏移量 for di in [-1, 0, 1]: for dj in [-1, 0, 1]: # 跳过自身位置 if di == 0 and dj == 0: continue # 计算相邻位置的坐标 neighbor_row = i + di neighbor_col = j + dj # 判断相邻位置是否在矩阵范围内,且是雷 if 0 <= neighbor_row < rows and 0 <= neighbor_col < cols and matrix[neighbor_row][neighbor_col]: mine_count += 1 result[i][j] = mine_count return result
思路2:遇到雷时,给周围有效位置加1(和你原思路更接近)
def minesweeper(matrix): rows = len(matrix) cols = len(matrix[0]) if rows else 0 result = [[0]*cols for _ in range(rows)] # 遍历每个单元格,找到雷的位置 for i in range(rows): for j in range(cols): if matrix[i][j]: # 遍历雷周围的8个方向 for di in (-1, 0, 1): for dj in (-1, 0, 1): # 跳过雷自身的位置 if di == 0 and dj == 0: continue # 计算相邻位置坐标 ni, nj = i + di, j + dj # 如果相邻位置在矩阵范围内,就给该位置计数+1 if 0 <= ni < rows and 0 <= nj < cols: result[ni][nj] += 1 return result
方案优势
- 不需要额外的边界处理,通过坐标有效性判断直接避免索引错误,逻辑更直观。
- 行/列遍历逻辑完全正确,不会漏掉任何单元格。
- 代码简洁易读,后续维护和调试都更方便。
测试你给出的输入 [[False, False, True], [False, False, False], [False, False, False]],两种实现都会输出正确结果:[[0, 1, 0], [0, 1, 0], [0, 1, 0]]。
内容的提问来源于stack exchange,提问作者TCB




