Description
Write a program to solve a Sudoku puzzle by filling the empty cells.
A sudoku solution must satisfy all of the following rules:
- Each of the digits
1-9 must occur exactly once in each row.
- Each of the digits
1-9 must occur exactly once in each column.
- Each of the digits
1-9 must occur exactly once in each of the 9 3x3 sub-boxes of the grid.
The '.' character indicates empty cells.
Example 1:
Input: board = [["5","3",".",".","7",".",".",".","."],["6",".",".","1","9","5",".",".","."],[".","9","8",".",".",".",".","6","."],["8",".",".",".","6",".",".",".","3"],["4",".",".","8",".","3",".",".","1"],["7",".",".",".","2",".",".",".","6"],[".","6",".",".",".",".","2","8","."],[".",".",".","4","1","9",".",".","5"],[".",".",".",".","8",".",".","7","9"]]
Output: [["5","3","4","6","7","8","9","1","2"],["6","7","2","1","9","5","3","4","8"],["1","9","8","3","4","2","5","6","7"],["8","5","9","7","6","1","4","2","3"],["4","2","6","8","5","3","7","9","1"],["7","1","3","9","2","4","8","5","6"],["9","6","1","5","3","7","2","8","4"],["2","8","7","4","1","9","6","3","5"],["3","4","5","2","8","6","1","7","9"]]
Explanation: The input board is shown above and the only valid solution is shown below:
Constraints:
board.length == 9
board[i].length == 9
board[i][j] is a digit or '.'.
- It is guaranteed that the input board has only one solution.
Solutions
Solution 1: Backtracking
We use arrays row, col, and box to record whether each number has appeared in each row, each column, and each 3x3 sub-box, respectively. If the number i has appeared in row r, column c, or the b-th 3x3 sub-box, then row[r][i], col[c][i], and box[b][i] are all set to true.
We iterate over every empty cell in the board and enumerate the possible numbers v that can be filled in. If v has not appeared in the current row, column, or 3x3 sub-box, we can try filling in v and continue searching for the next empty cell. If we reach the end and all cells are filled, it means we have found a valid solution.
PythonJavaC++GoC#PHP
class Solution:
def solveSudoku(self, board: List[List[str]]) -> None:
def dfs(k):
nonlocal ok
if k == len(t):
ok = True
return
i, j = t[k]
for v in range(9):
if row[i][v] == col[j][v] == block[i // 3][j // 3][v] == False:
row[i][v] = col[j][v] = block[i // 3][j // 3][v] = True
board[i][j] = str(v + 1)
dfs(k + 1)
row[i][v] = col[j][v] = block[i // 3][j // 3][v] = False
if ok:
return
row = [[False] * 9 for _ in range(9)]
col = [[False] * 9 for _ in range(9)]
block = [[[False] * 9 for _ in range(3)] for _ in range(3)]
t = []
ok = False
for i in range(9):
for j in range(9):
if board[i][j] == '.':
t.append((i, j))
else:
v = int(board[i][j]) - 1
row[i][v] = col[j][v] = block[i // 3][j // 3][v] = True
dfs(0)(code-box)
class Solution {
private boolean ok;
private char[][] board;
private List<Integer> t = new ArrayList<>();
private boolean[][] row = new boolean[9][9];
private boolean[][] col = new boolean[9][9];
private boolean[][][] block = new boolean[3][3][9];
public void solveSudoku(char[][] board) {
this.board = board;
for (int i = 0; i < 9; ++i) {
for (int j = 0; j < 9; ++j) {
if (board[i][j] == '.') {
t.add(i * 9 + j);
} else {
int v = board[i][j] - '1';
row[i][v] = col[j][v] = block[i / 3][j / 3][v] = true;
}
}
}
dfs(0);
}
private void dfs(int k) {
if (k == t.size()) {
ok = true;
return;
}
int i = t.get(k) / 9, j = t.get(k) % 9;
for (int v = 0; v < 9; ++v) {
if (!row[i][v] && !col[j][v] && !block[i / 3][j / 3][v]) {
row[i][v] = col[j][v] = block[i / 3][j / 3][v] = true;
board[i][j] = (char) (v + '1');
dfs(k + 1);
row[i][v] = col[j][v] = block[i / 3][j / 3][v] = false;
}
if (ok) {
return;
}
}
}
}(code-box)
class Solution {
public:
void solveSudoku(vector<vector<char>>& board) {
bool row[9][9] = {false};
bool col[9][9] = {false};
bool block[3][3][9] = {false};
bool ok = false;
vector<pair<int, int>> t;
for (int i = 0; i < 9; ++i) {
for (int j = 0; j < 9; ++j) {
if (board[i][j] == '.') {
t.push_back({i, j});
} else {
int v = board[i][j] - '1';
row[i][v] = col[j][v] = block[i / 3][j / 3][v] = true;
}
}
}
auto dfs = [&](this auto&& dfs, int k) -> void {
if (k == t.size()) {
ok = true;
return;
}
int i = t[k].first, j = t[k].second;
for (int v = 0; v < 9; ++v) {
if (!row[i][v] && !col[j][v] && !block[i / 3][j / 3][v]) {
row[i][v] = col[j][v] = block[i / 3][j / 3][v] = true;
board[i][j] = v + '1';
dfs(k + 1);
row[i][v] = col[j][v] = block[i / 3][j / 3][v] = false;
}
if (ok) {
return;
}
}
};
dfs(0);
}
};(code-box)
func solveSudoku(board [][]byte) {
var row, col [9][9]bool
var block [3][3][9]bool
var t [][2]int
ok := false
for i := 0; i < 9; i++ {
for j := 0; j < 9; j++ {
if board[i][j] == '.' {
t = append(t, [2]int{i, j})
} else {
v := int(board[i][j] - '1')
row[i][v], col[j][v], block[i/3][j/3][v] = true, true, true
}
}
}
var dfs func(int)
dfs = func(k int) {
if k == len(t) {
ok = true
return
}
i, j := t[k][0], t[k][1]
for v := 0; v < 9; v++ {
if !row[i][v] && !col[j][v] && !block[i/3][j/3][v] {
row[i][v], col[j][v], block[i/3][j/3][v] = true, true, true
board[i][j] = byte(v + '1')
dfs(k + 1)
row[i][v], col[j][v], block[i/3][j/3][v] = false, false, false
}
if ok {
return
}
}
}
dfs(0)
}(code-box)
public class Solution {
public void SolveSudoku(char[][] board) {
bool[,] row = new bool[9, 9];
bool[,] col = new bool[9, 9];
bool[,,] block = new bool[3, 3, 9];
bool ok = false;
var t = new List<(int, int)>();
for (int i = 0; i < 9; ++i) {
for (int j = 0; j < 9; ++j) {
if (board[i][j] == '.') {
t.Add((i, j));
} else {
int v = board[i][j] - '1';
row[i, v] = col[j, v] = block[i / 3, j / 3, v] = true;
}
}
}
void Dfs(int k) {
if (k == t.Count) {
ok = true;
return;
}
var (i, j) = t[k];
for (int v = 0; v < 9; ++v) {
if (!row[i, v] && !col[j, v] && !block[i / 3, j / 3, v]) {
row[i, v] = col[j, v] = block[i / 3, j / 3, v] = true;
board[i][j] = (char)(v + '1');
Dfs(k + 1);
if (ok) return;
row[i, v] = col[j, v] = block[i / 3, j / 3, v] = false;
}
}
}
Dfs(0);
}
}(code-box)
class Solution {
/**
* @param String[][] $board
* @return NULL
*/
function solveSudoku(&$board) {
$row = array_fill(0, 9, array_fill(0, 9, false));
$col = array_fill(0, 9, array_fill(0, 9, false));
$block = array_fill(0, 3, array_fill(0, 3, array_fill(0, 9, false)));
$ok = false;
$t = [];
for ($i = 0; $i < 9; ++$i) {
for ($j = 0; $j < 9; ++$j) {
if ($board[$i][$j] === '.') {
$t[] = [$i, $j];
} else {
$v = ord($board[$i][$j]) - ord('1');
$row[$i][$v] = true;
$col[$j][$v] = true;
$block[intval($i / 3)][intval($j / 3)][$v] = true;
}
}
}
$dfs = function ($k) use (&$dfs, &$board, &$row, &$col, &$block, &$ok, &$t) {
if ($k === count($t)) {
$ok = true;
return;
}
[$i, $j] = $t[$k];
for ($v = 0; $v < 9; ++$v) {
if (!$row[$i][$v] && !$col[$j][$v] && !$block[intval($i / 3)][intval($j / 3)][$v]) {
$row[$i][$v] = $col[$j][$v] = $block[intval($i / 3)][intval($j / 3)][$v] = true;
$board[$i][$j] = chr($v + ord('1'));
$dfs($k + 1);
if ($ok) {
return;
}
$row[$i][$v] = $col[$j][$v] = $block[intval($i / 3)][intval($j / 3)][
$v
] = false;
}
}
};
$dfs(0);
}
}(code-box)