leetcode-37-解数独

leetcode-37-解数独

编写一个程序,通过已填充的空格来解决数独问题。
一个数独的解法需遵循如下规则:

数字 1-9 在每一行只能出现一次。
数字 1-9 在每一列只能出现一次。
数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。
空白格用 '.' 表示。

一个数独。
在这里插入图片描述
答案被标成红色。
在这里插入图片描述
Note:

给定的数独序列只包含数字 1-9 和字符 '.' 。
你可以假设给定的数独只有唯一解。
给定数独永远是 9x9 形式的。

思路
数独的解法肯定是回溯法,也可以理解成DFS,对于数独而言一个就是有限编程(每个位置的选择并不是都是0-9),一个就是回溯
类似人的思考方式去尝试,行,列,还有 3*3 的方格内数字是 1~9 不能重复。

我们尝试填充,如果发现重复了,那么擦除重新进行新一轮的尝试,直到把整个数组填充完成。

算法步骤:

  • 数独首先行,列,还有 3*3 的方格内数字是 1~9 不能重复。
  • 声明布尔数组,表明行列中某个数字是否被使用了, 被用过视为 true,没用过为 false。
  • 初始化布尔数组,表明哪些数字已经被使用过了。
  • 尝试去填充数组,只要行,列, 还有 3*3 的方格内 出现已经被使用过的数字,我们就不填充,否则尝试填充。
  • 如果填充失败,那么我们需要回溯。将原来尝试填充的地方改回来。
  • 递归直到数独被填充完成。
# DFS 
class Solution:
    def solveSudoku(self, board: List[List[str]]) -> None:
        """
        Do not return anything, modify board in-place instead.
        """
        col = [set() for i in range(9)]
        row = [set() for i in range(9)]
        sqr = [[set() for i in range(3)] for i in range(3)]
        for i in range(9):
            for j in range(9):
                if board[i][j] != '.':
                    col[j].add(board[i][j])
                    row[i].add(board[i][j])
                    sqr[i//3][j//3].add(board[i][j])
        
        def dfs(i, j):
            if board[i][j] != '.':
                if i == 8 and j == 8:
                    self.flag = True
                    return
                if j < 8:
                    dfs(i, j+1)
                else:
                    dfs(i+1, 0)
                return
            for ch in range(1, 10):
                ch = str(ch)
                if ch not in col[j] and ch not in row[i] and ch not in sqr[i//3][j//3]:
                    #print(i, j, ch)
                    col[j].add(ch)
                    row[i].add(ch)
                    sqr[i//3][j//3].add(ch)
                    board[i][j] = ch
                    if i == 8 and j == 8:
                        self.flag = True
                        return
                    if j < 8:
                        dfs(i, j+1)
                    else:
                        dfs(i+1, 0)
                    if self.flag: return
                    board[i][j] = '.'
                    col[j].remove(ch)
                    row[i].remove(ch)
                    sqr[i//3][j//3].remove(ch)
        self.flag = False
        dfs(0, 0)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章