/**
* @param {character[][]} board
* @return {void} Do not return anything, modify board in-place instead.
*/
var solveSudoku = function (board) {
// 记录每行已填的数字
const rows = matrix(9);
// 记录每列已填的数字
const cols = matrix(9);
// 记录每个小宫已填的数字
const boxes = matrix(3, 3);
// 记录所有空格子的坐标
const spaces = [];
// 遍历数独:
// 1. 找空格
// 2. 标记已填数字
board.forEach((row, x) =>
row.forEach((cell, y) => {
// 记录空格的坐标
if (cell === '.') spaces.push([x, y]);
// 不是空格的话,标记这个数字已经使用
else mark(x, y, cell, true);
}),
);
// 开始填空格
dfs(0);
// *******************************************
function dfs(pos) {
// 所有空格都填完了,说明这条路是通的,返回 true
if (pos >= spaces.length) return true;
const [x, y] = spaces[pos];
// 1~9 的数字都试着填一遍
for (let n = 1; n <= 9; n++) {
// 同一行、同一列、同一个小宫出现过的数字不能填
if (!isValidDigit(x, y, n)) continue;
// 填入数字
board[x][y] = n + '';
mark(x, y, n, true);
// 递归填下一个空格
const res = dfs(pos + 1);
// 回溯
mark(x, y, n, false);
// 如果这条路可行,就可以提前返回了
// 不然递归回来会进入下一个循环
// 就把原来填的数字覆盖了
if (res) return true;
}
}
// 根据坐标判断是哪个小宫里的格子
function getBox(x, y) {
return boxes[(x / 3) >> 0][(y / 3) >> 0];
}
// 检查对应的行和列,还有小宫里有没有出现过该数字
function isValidDigit(x, y, n) {
return !rows[x][n] && !cols[y][n] && !getBox(x, y)[n];
}
// 标记已填数字
function mark(x, y, n, status) {
rows[x][n] = cols[y][n] = getBox(x, y)[n] = status;
}
function matrix(rows = 0, cols = 0) {
return Array(rows)
.fill(0)
.map(_ => (cols === 0 ? {} : matrix(cols, 0)));
}
};
Python Code
class Solution(object):
def solveSudoku(self, board):
"""
:type board: List[List[str]]
:rtype: None Do not return anything, modify board in-place instead.
"""
rows = [[False]*9 for _ in range(9)]
cols = [[False]*9 for _ in range(9)]
boxes = [[[False]*9 for _ in range(3)] for _ in range(3)]
def mark(x, y, n, status):
rows[x][n] = cols[y][n] = boxes[x // 3][y // 3][n] = status
def valid(x, y, n):
return (not rows[x][n]) and (not cols[y][n]) and (not boxes[x // 3][y // 3][n])
def dfs(pos):
if pos >= len(spaces): return True
x, y = spaces[pos]
for n in range(9):
if not valid(x, y, n): continue
board[x][y] = str(n + 1)
mark(x, y, n, True)
if dfs(pos + 1): return True
mark(x, y, n, False)
spaces = []
for x in range(9):
for y in range(9):
cell = board[x][y]
if cell == '.':
spaces.append((x, y))
else:
mark(x, y, int(cell) - 1, True)
dfs(0)