[
dfs
hash table
2d-array
]
Leetcode 0037. Sudoku Solver
Problem statement
https://leetcode.com/problems/sudoku-solver/
Solution
The idea here is to use dfs(board, empty, rows, cols, boxes) function, where:
boardis current board we have.emptyis list of empty cells.rowsis defaultict, where for each of9rows we have set of values we have in this row, similar logic forcolsandboxes.
What we do in our dfs backtracking algorithm is to choose any empty cell, and then try to put some number in this cell from the numbers we did not have on the same row, column or box, and run dfs with new arguments:
- We look at
row[r],cols[c]andboxes[3*(r//3)+c//3], and remove this elements fromset("123456789") - Make
board[r][c] = k. - Add
kto corresponding row, column and box. - Run
dfsrecursively and if we found solution, returnTrue. - Delete
kfrom corresponding row, column and box.
Complexity
Time complexity of one dfs step is O(1), because we actually need to check row, column and box. However it is difficult to estimate overall complexity of algorithm - I think it is exponential at least. Space complexity is O(1).
Code
class Solution:
def solveSudoku(self, board):
def dfs(board, empty, rows, cols, boxes):
if not empty: return True
r, c = empty[-1]
for k in set("123456789") - (rows[r]|cols[c]|boxes[3*(r//3)+c//3]):
board[r][c] = k
for dic in [rows[r], cols[c], boxes[3*(r//3)+c//3]]:
dic.add(k)
if dfs(board, empty[:-1], rows, cols, boxes): return True
board[r][c] = '.'
for dic in [rows[r], cols[c], boxes[3*(r//3)+c//3]]:
dic.remove(k)
return False
cols, rows, boxes, empty = defaultdict(set), defaultdict(set), defaultdict(set), []
for r, c in product(range(9), range(9)):
if board[r][c] == ".":
empty.append((r,c))
else:
for dic in [rows[r], cols[c], boxes[3*(r//3)+c//3]]:
dic.add(board[r][c])
dfs(board, empty, rows, cols, boxes)