• [LeetCode in Python] 37 (H) sudoku solver 解数独


    题目

    https://leetcode-cn.com/problems/sudoku-solver/

    编写一个程序,通过已填充的空格来解决数独问题。

    一个数独的解法需遵循如下规则:

    数字1-9在每一行只能出现一次。
    数字1-9在每一列只能出现一次。
    数字1-9在每一个以粗实线分隔的3x3宫内只能出现一次。

    空白格用 '.' 表示。

    一个数独。

    答案被标成红色。

    Note:

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

    解题思路

    • DFS + Backtracking
    • 使用3个列表存储行、列、格的已有数字状态。
    • 为了代码精简,将几个常用逻辑提炼为函数了。
    • 先根据当前情况,初始化3个列表。
    • 然后是标准回溯框架:
      • 一进来先判断是否到底了,
      • 然后得出下一步的坐标,
      • 如果当前位置有数字,在下一步坐标上递归调用backtracking函数
      • 如果当前位置是空白,那么循环遍历1-9
        • 先看该数字是否违和
        • 如果OK,就更新3个列表,并在数独表格中设置该数字
        • 然后在下一步坐标上递归调用backtracking函数
        • 如果返回False,则恢复3个列表,并擦掉数独表格中填入的数字
      • 到此返回False
    • 主程序入口:backtracking(0,0)

    代码

    class Solution:
        def solveSudoku(self, board: List[List[str]]) -> None:
            """
            Do not return anything, modify board in-place instead.
            """
    
            row_list = [[False]*10 for _ in range(9)]
            col_list = [[False]*10 for _ in range(9)]
            grid_list = [[False]*10 for _ in range(9)]
    
            # - get grid index
            def get_grid_index(row,col):
                return (row//3)*3 + col//3
    
            # - set state to value (True/False)
            def set_state(row, col, num, value):
                row_list[row][num] = value
                col_list[col][num] = value
                grid_list[get_grid_index(row, col)][num] = value
    
            # - init state
            for row in range(9):
                for col in range(9):
                    c = board[row][col]
                    if c != '.': 
                        set_state(row, col, int(c), True)
    
            # - check if num is valid at (row, col)
            def is_valid(row, col, num):
                return not any([
                    row_list[row][num],
                    col_list[col][num],
                    grid_list[get_grid_index(row,col)][num]
                ])
    
            # - backtracking
            def backtracking(row, col):
                # - exit if out of boundary
                if row == 9:
                    return True
    
                # - get next position
                next_col = (col + 1) % 9
                next_row = row+1 if next_col==0 else row
    
                # - only expand for '.'
                c = board[row][col]
                if c != '.': 
                    return backtracking(next_row, next_col)
    
                # - try 1..9 
                for i in range(1,10):
                    if not is_valid(row, col, i): continue
    
                    # - update state
                    set_state(row, col, i, True)
                    board[row][col] = '%s' % i
    
                    # - go to next pos
                    if backtracking(next_row, next_col): 
                        return True
                    
                    # - restore state
                    set_state(row, col, i, False)
                    board[row][col] = '.'
                    
                return False
    
            # - backtracking from (0,0)
            backtracking(0,0)
    
  • 相关阅读:
    JavaScript实现文本框和密码框placeholder效果(兼容ie8)
    11.24 模拟赛题解
    一句话题解集——口胡万岁
    uTools-插件化定制属于自己的工具集[免费]
    tree
    braintree 支付
    Shopify 接口调用
    TcPlayer腾讯播放器
    微信支付(WeixinJSBridge.invoke、wx.chooseWXPay)
    图片上传(二进制文件流)
  • 原文地址:https://www.cnblogs.com/journeyonmyway/p/12694063.html
Copyright © 2020-2023  润新知