• 【LeetCode每日一题】——37.解数独


    一【题目类别】

    • 数组

    二【题目难度】

    • 困难

    三【题目编号】

    • 37.解数独

    四【题目描述】

    • 编写一个程序,通过填充空格来解决数独问题。
    • 数独的解法需 遵循如下规则:
    • 数字 1-9 在每一行只能出现一次。
    • 数字 1-9 在每一列只能出现一次。
    • 数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。(请参考示例图)
    • 数独部分空格内已填入了数字,空白格用 ‘.’ 表示。

    五【题目示例】

    • 示例 1:
      • 在这里插入图片描述
      • 输入: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”]]
      • 输出:[[“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”]]
      • 解释:输入的数独如上图所示,唯一有效的解决方案如下所示:
      • 在这里插入图片描述

    六【解题思路】

    • 此题有难度,但是还是回溯的思想。回溯算法的模板如下:
    void backTracking(参数)
    {
    	if(终止条件)
    	{
    		保存结果;
    		return;
    	}
    	for(遍历从当前位置出发的所有“路径”)
    	{
    		保存“路径”节点;
    		backTracking(所需参数);
    		回溯处理,删除上一步保存的“路径”节点,准备进行新的递归
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 有了以上模板,我们只需要往里面填入解决这道题所需的“工具”,首先有几个定义我们要清楚:
      • row[i][digit]:表示digit这个数字出现在了第i行
      • col[j][digit]:表示digit这个数字出现在了第j列
      • block[i][j][dight]:表示digit这个数字出现在了第i、j块
      • valid:表示是否应该结束递归
      • spaces:存储需要填入数字的位置
    • 首先遍历整个二维数组,当我们遍历到某个位置:
      • 如果此位置是“.”:说明需要填入数字,那么将此位置存入spaces,准备填入数字
      • 如果此位置是数字:那将此行、此列和此块对应这个数字都置为true,也就是不能再出现这个数字了
    • 然后进入递归算法,这里面就简单了,就是上面模板写的过程,只需要判断当前数字是否出现在此行、此列和此块即可
    • 此外还需要注意真正的数字和数组下标之间的关系
    • 其他细节可以参考代码
    • 最后不需要返回值

    七【题目提示】

    • b o a r d . l e n g t h = = 9 board.length == 9 board.length==9
    • b o a r d [ i ] . l e n g t h = = 9 board[i].length == 9 board[i].length==9
    • b o a r d [ i ] [ j ] 是 一 位 数 字 或 者 ′ . ′ board[i][j] 是一位数字或者 '.' board[i][j].
    • 题 目 数 据 保 证 输 入 数 独 仅 有 一 个 解 题目数据 保证 输入数独仅有一个解

    八【时间频度】

    • 时间复杂度: O ( n ) O(n) O(n),其中 n n n为输入数组的行数/列数
    • 空间复杂度: O ( 1 ) O(1) O(1)

    九【代码实现】

    1. Java语言版
    package Array;
    
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * @Author: IronmanJay
     * @Description: 37.解数独
     * @CreateTime: 2022-11-26  09:36
     */
    public class p37_SudokuSolver {
    
        public static void main(String[] args) {
            char[][] 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'}};
            solveSudoku(board);
        }
    
        private static boolean[][] row = new boolean[9][9];
        private static boolean[][] col = new boolean[9][9];
        private static boolean[][][] block = new boolean[3][3][9];
        private static boolean valid = false;
        private static List<int[]> spaces = new ArrayList<int[]>();
    
        public static void solveSudoku(char[][] board) {
            for (int i = 0; i < 9; i++) {
                for (int j = 0; j < 9; j++) {
                    if (board[i][j] == '.') {
                        spaces.add(new int[]{i, j});
                    } else {
                        int digit = board[i][j] - '0' - 1;
                        row[i][digit] = true;
                        col[j][digit] = true;
                        block[i / 3][j / 3][digit] = true;
                    }
                }
            }
            dfs_back_p37_SudokuSolver(board, 0);
        }
    
        public static void dfs_back_p37_SudokuSolver(char[][] board, int pos) {
            if (pos == spaces.size()) {
                valid = true;
                return;
            }
            int[] space = spaces.get(pos);
            int i = space[0];
            int j = space[1];
            for (int digit = 0; digit < 9 && !valid; digit++) {
                if (!row[i][digit] && !col[j][digit] && !block[i / 3][j / 3][digit]) {
                    row[i][digit] = true;
                    col[j][digit] = true;
                    block[i / 3][j / 3][digit] = true;
                    board[i][j] = (char) (digit + '0' + 1);
                    dfs_back_p37_SudokuSolver(board, pos + 1);
                    row[i][digit] = false;
                    col[j][digit] = false;
                    block[i / 3][j / 3][digit] = false;
                }
            }
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    1. C语言版
    #include
    #include
    #include
    
    bool row[9][9];
    bool col[9][9];
    bool block[3][3][9];
    bool valid;
    int* spaces[81];
    int spaceSize;
    
    void dfs_back_p37_SudokuSolver(char** board, int pos)
    {
    	if (pos == spaceSize)
    	{
    		valid = true;
    		return;
    	}
    	int i = spaces[pos][0];
    	int j = spaces[pos][1];
    	for (int digit = 0; digit < 9 && !valid; digit++)
    	{
    		if (!row[i][digit] && !col[j][digit] && !block[i / 3][j / 3][digit])
    		{
    			row[i][digit] = true;
    			col[j][digit] = true;
    			block[i / 3][j / 3][digit] = true;
    			board[i][j] = digit + '0' + 1;
    			dfs_back_p37_SudokuSolver(board, pos + 1);
    			row[i][digit] = false;
    			col[j][digit] = false;
    			block[i / 3][j / 3][digit] = false;
    		}
    	}
    }
    
    void solveSudoku(char** board, int boardSize, int* boardColSize)
    {
    	memset(row, false, sizeof(row));
    	memset(col, false, sizeof(col));
    	memset(block, false, sizeof(block));
    	valid = false;
    	spaceSize = 0;
    	for (int i = 0; i < 9; i++)
    	{
    		for (int j = 0; j < 9; j++)
    		{
    			if (board[i][j] == '.')
    			{
    				spaces[spaceSize] = malloc(sizeof(int) * 2);
    				spaces[spaceSize][0] = i;
    				spaces[spaceSize++][1] = j;
    			}
    			else
    			{
    				int digit = board[i][j] - '0' - 1;
    				row[i][digit] = true;
    				col[j][digit] = true;
    				block[i / 3][j / 3][digit] = true;
    			}
    		}
    	}
    	dfs_back_p37_SudokuSolver(board, 0);
    }
    
    /*主函数省略*/
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66

    十【提交结果】

    1. Java语言版
      在这里插入图片描述

    2. C语言版
      在这里插入图片描述

  • 相关阅读:
    如何使用 pyqt 实现 Groove 音乐播放器
    arcgis pro中的底图
    Shell 脚本
    ESP32 Micropython编程(Thonny)01----环境搭建&点灯
    要不要做全链路压测
    互联网采集数据有哪几种常见的方法?
    C++学习笔记--项目知识点集合
    十几年Java“老油条”,教你如何才能把Java学好学透彻
    JavaWeb后端开发 JWT令牌解析 登录校验 通用模板/SpringBoot整合
    学编程:Python入门考级必备[5]
  • 原文地址:https://blog.csdn.net/IronmanJay/article/details/128048008