文章目录
- 一【题目类别】
- 二【题目难度】
- 三【题目编号】
- 四【题目描述】
- 五【题目示例】
- 六【解题思路】
- 七【题目提示】
- 八【时间频度】
- 九【代码实现】
- 十【提交结果】
一【题目类别】
- 数组
二【题目难度】
- 困难
三【题目编号】
- 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(所需参数);
回溯处理,删除上一步保存的“路径”节点,准备进行新的递归
}
}
- 有了以上模板,我们只需要往里面填入解决这道题所需的“工具”,首先有几个定义我们要清楚:
- 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)
九【代码实现】
- 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;
}
}
}
}
- C语言版
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
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);
}
/*主函数省略*/
十【提交结果】
-
Java语言版
-
C语言版