leetcode37 解数独问题 hard

这篇博客介绍了一种使用回溯算法解决数独问题的方法。作者从基础思路出发,详细阐述了如何设计一个递归函数helper,该函数通过穷举1到9并在每个位置检查数独的有效性。当找到一个有效数字时,会继续递归填充下一个位置。如果所有可能的数字都不能使数独完成,则回溯到上一个位置尝试其他数字。博客通过这种方式深入浅出地解释了回溯算法的应用,帮助初学者理解这种算法。
摘要由CSDN通过智能技术生成

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

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

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/sudoku-solver

作为一个刚刚起步算法的小弱鸡,稍微记录一下自己对于这题的设计思路吧,没有尝试高大上的办法,我只用了最简单的回溯办法,但是这道题确实加深了我对于回溯的理解。
基本思路是对于一个数独矩阵,设计一个函数helper(board,row,col),对于board[row][col]按进行1-9穷举,并判断isvalid,如果这一位填的数字满足数独矩阵条件,那么就判断helper(board,row,col+1),这里需要思考的是我们希望这个递归函数的意义是什么,我的回答是,我希望输入board,row,col能够判断这之后的整个数独能不能填完,以此为基点思考下去就会遇到一个问题:
最开始我设计的辅助函数是一个无返回的void函数,但是我发现这样子无法知道后一位helper(board,row,col+1)是否能够填完,所以将函数改为bool函数,那么helper(board,row,col)的返回值判断思路如下:
如果board[row][col]填了数字或者能填数字,那么就判断helper(board,row,col+1)是否是true,如果是那么返回true;不是那就说明这一位填的数字不对,那就换一个数字,如果穷举完9个数字都没有返回true,那就说明helper(board,row,col)无法完成数独,所以return false。
回溯的思想则体现在中间每次将choose的数字改回’.'的过程。

class Solution {
public:
    void solveSudoku(vector<vector<char>>& board) {
        helper(board,0,0);
    }
    //输入位置返回是否能填成功
    bool helper(vector<vector<char>>& board,int row,int col){
        if(row==8&&col==9){
            //base case
            return true;
        }
        //位置变化
        if(col==9){
            col=0;
            row++;
        }
        //如果已经有数字了
        if(board[row][col]!='.') return helper(board,row,col+1);
        //没数字的话穷举此位置1-9
        else{
            for(int i=1;i<10;i++){
                //choose
                board[row][col]=(char)(i+'0');
                bool flag=isvalid(row,col,board);
                if(flag) {
                    if(helper(board,row,col+1)) return true;
                }
                //unchoose
                board[row][col]='.';
            }
            //如果9个数都举完,仍然不能返回true,说明是之前选的数字出错了,因此返回false
            return false;
        }
    }
    bool isvalid(int row,int col,vector<vector<char>>& board){
        int num=board[row][col];
        for(int i=0;i<9;i++){
            if(i==col) continue;
            if(board[row][i]==num) return false;
        }
        for(int i=0;i<9;i++){
            if(i==row) continue;
            if(board[i][col]==num) return false;
        }
        int a=row/3;
        int b=col/3;
        for(int i=a*3;i<(a+1)*3;i++){
            for(int j=b*3;j<(b+1)*3;j++){
                if(row==i&&col==j) continue;
                if(board[i][j]==num) return false;
            }
        }
        return true;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值