(回溯) LeetCode 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"]

解释:输入的数独如上图所示,唯一有效的解决方案如下所示:

提示:

board.length == 9

boardi.length == 9

boardij 是一位数字或者 '.'

题目数据 保证 输入数独仅有一个解

二. 解题思路

本题是回溯中较难的一个题目,需要你通过回溯的方法实现解数独,玩过数独的同学一定十分清楚,数独就是同行同列不能有相同的数字出现,然后同九宫格不能有相同的数字出现。

这道题看似抽象,好像和上一道的N皇后千差万别,但是做起来思路都是很简单的,N皇后的意思是每行每列以及对角线只能由一个Q,我们使用一层循环来遍历每一行,然后通过一个isValid 函数判断当前位置放置皇后是否合法,当然本题也十分简单,只不过这个题需要你通过两层for 循环去遍历每一个位置,然后判断每一个位置放置某一数字是否合法,话不多说,我们进行回溯的三件套!

  1. 确定递归参数:由于题目中只需要返回一个board 的二维字符数组,所以我们只需要传入一个board 数组就可以了,但是这个题目不像之前做的一样需要收集行多种结果,这个是只要有符合条件的就直接返回,所以我们将返回值类型定为bool 方便判断。

  2. 递归终止条件:本题没有。

  3. 单层循环:我们需要两层循环来遍历board 数组,外层遍历行,内层遍历列,然后判断每一个点是否为空白格,即('.') ,如果是,就再加一个for 循环,从1 到9 去枚举符合条件的答案,然后再去递归,回溯,就可以了,如果遍历了9 个数都没有找到符合条件的答案,那么直接return false 即可。

下图是代码随想录中的一个对递归以及回溯总结的流程图,大家可以了解一下。

话不多说!!!上代码!!

三. 代码

cpp 复制代码
class Solution {
public:
    bool isValid(int row, int col, int val, vector<vector<char>>& board){
        // 判断同行
        for(int i = 0; i < 9; i++){
            if(board[row][i] == val) return false;
        }
        // 判断同列
        for(int i = 0; i < 9; i++){
            if(board[i][col] == val) return false;
        }
        // 判断同九宫格
        int startrow = (row / 3) * 3;
        int startcol = (col / 3) * 3;
        for(int i = startrow; i < startrow + 3; i++){
            for(int j = startcol; j < startcol + 3; j++){
                if(board[i][j] == val) return false;
            }
        }
        return true;
    }

    bool back(vector<vector<char>>& board){
        for(int i = 0; i < board.size(); i++){
            for(int j = 0; j < board[0].size(); j++){
                if(board[i][j] == '.'){
                    for(char k = '1'; k <= '9'; k++){       // 九个数字一个一个试
                        if(isValid(i, j, k, board)){
                            board[i][j] = k;
                            if(back(board)) return true;
                            board[i][j] = '.';
                        }
                    }
                    return false;       // 九个数都试完了还没答案就说明没结果
                }
            }
        }
        return true;
    }
    void solveSudoku(vector<vector<char>>& board) {
        back(board);
    }
};

四. 总结

本题是回溯算法中的难题了,大家可以先看我之前的题目,然后练习会之前的题目之后再看这题会容易很多。

时间复杂度:O(1);

空间复杂度:O(1)。

喜欢的话给个关注吧!!

相关推荐
2601_970703831 小时前
工业除湿机租赁:把一份租金合同拆开看
大数据·数据结构·算法·数据库架构·推荐算法
心中有你02141 小时前
Java实现Dijkstra最短路径算法(邻接表 + 优先队列)
java·数据库·算法
ZhengEnCi2 小时前
同样的模型,为什么本地和云 API 差别那么大:量化精度、聊天模板与采样参数的三大元凶
人工智能·算法·llm
会编程的小孩3 小时前
C++ 定时器
c++
Flynn Liang3 小时前
RAG 答非所问/幻觉怎么破?Spring AI QuestionAnswerAdvisor 召回优化实战(TopK/重排/混合检索)
人工智能·算法·spring·rag·幻觉·springai
liminla!3 小时前
SQL 从入门到进阶:语法速查与实战练习(完整优化版)
数据库·sql·算法
沫璃染墨4 小时前
从零入门计算机网络系列(十一):HTTP协议进阶——从重定向原理到GET/POST与Fiddler抓包
linux·服务器·开发语言·网络·c++·tcp/ip·html
维克兜率天4 小时前
【维克】指数调整:哪些股票会被“强制买入“?
人工智能·python·算法
罗西的思考5 小时前
【轻量化复刻大模型】线性注意力交互式演示
人工智能·算法·机器学习
神也畏惧菠萝5 小时前
Day08 Python流程控制从入门到上瘾:if/match/while/for四件套,从B站登录一路打到猜数字游戏
python·算法·数据存储·for·while·if·ifelse