- Sudoku Solver
困难
https://leetcode.cn/problems/sudoku-solver/
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.
相关企业
- 微软 Microsoft|9
- 亚马逊 Amazon|9
- 苹果 Apple|6
- 谷歌 Google|5
- 优步 Uber|3
- Facebook|2
相关标签
- Array
- Backtracking
- Matrix
相似题目
- Valid Sudoku 中等
- Unique Paths III 困难
对于这道题目来说,我们要明确几点
- 目标(base case) :填满每个格子。
- 选择列表(choice list):每个空的格子可以填入1-9这九个数字。
- 约束条件(constrain):1-9在每一行、每一列和每个3x3的大格中都只能出现一次。
- 选择路径(path):由于我们是inplace操作,board就存储了已经做过的选择。
我们在这里设置backtrack函数的返回类型为bool,这样一来,当程序找到可行解后就能终止递归。
时间复杂度是常数。由于数独的大小是固定的,因此没有 N 变量来衡量。上限是(9!)^9 。
对第一行来说,第一个格子不会超过9种情况,
第二个格子不会超过8种...
所以第一行不会超过9!个情况。
那么所有行不会超过(9!)^2
数独大小固定,空间用来存储数独,行,列和子方块的结构,每个有 81 个元素。
def dfs(self, board, rowi, colj):
if self.isCompletedSudoku(board):
return True
for add_number in range(1, 10):
if not self.isValidNewStep(board, str(add_number), rowi, colj):
continue
board[rowi][colj] = str(add_number)
if self.dfs(board, rowi, colj+1):
return True
board[rowi][colj] = "."
return False
下面是完整版:
class Solution:
def solveSudoku(self, board: List[List[str]]) -> None:
"""
Do not return anything, modify board in-place instead.
"""
self.dfs(board, 0, 0)
def dfs(self, board, rowi, colj):
if self.isCompletedSudoku(board):
return True
if colj == 9:
rowi += 1
colj = 0
if rowi == 9:
return True
if board[rowi][colj] != ".":
return self.dfs(board, rowi, colj+1)
for add_number in range(1, 10):
if not self.isValidNewStep(board, str(add_number), rowi, colj):
continue
board[rowi][colj] = str(add_number)
if self.dfs(board, rowi, colj+1):
return True
board[rowi][colj] = "."
return False
def isCompletedSudoku(self, board):
for rowi in range(9):
for colj in range(9):
if board[rowi][colj] == ".":
return False
return True
def isValidNewStep(self, board, new_number, rowi, colj):
for i in range(9):
# check all cells in same row
if board[rowi][i] == new_number:
return False
# check all cells in same col
if board[i][colj] == new_number:
return False
# check all cells in same 9-cells-small-sudoku
nineCellSudoku_rowi = rowi // 3
nineCellSudoku_colj = colj // 3
for i in range(3):
for j in range(3):
if board[nineCellSudoku_rowi * 3 + i][nineCellSudoku_colj * 3 + j] == new_number:
return False
return True