解数独——回溯

该文介绍了如何利用回溯法解决数独问题,通过二维递归的暴力搜索策略,遵循数独的规则,确保每个数字在行、列和3x3宫格中唯一。代码中定义了backtracking函数进行递归搜索,同时isValid函数检查当前位置填入数字的合法性。当找到解决方案时立即返回,否则进行回溯。
摘要由CSDN通过智能技术生成


问题

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

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

数字 1-9 在每一行只能出现一次。
数字 1-9 在每一列只能出现一次。
数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。(请参考示例图)
数独部分空格内已填入了数字,空白格用 ‘.’ 表示。


一、解题思路

使用二维递归来暴力搜索,递归的结束条件是找到满足条件的方案就立刻返回,因为正确方案只有一个,递归返回值需要bool类型,这样便于实现找到解决方案立刻返回,而不是进行回溯修改原来的方案。
本题不需要写终止条件,因为找到解决方案自然就立刻返回了,这也是暴力搜索的本质。
遍历逻辑是用两个for循环遍历行和列,一个有趣的地方是填通过判断位置是否是数字来保证下一层的棋盘一定比上一层的棋盘多一个数,因为上一层棋盘放了数后,下一层通过判断是否有数字来跳过本次循环,另外需要使用一个for循环来判断放数字的可能性。

二、代码

class Solution {
private:
    bool backtracking(int row, int col, vector<vector<char>>& board){
        for (int i=row; i<board.size(); i++){
            for (int j=col; j<board.size(); j++){
                if (board[i][j]!='.'){
                    continue;
                }
                for (char k='1'; k<='9'; k++){
                    if (isvalid(board, i, j, k)){
                        board[i][j] = k;
                        if (backtracking(i, j, board)) return true;
                        board[i][j] = '.';
                    }
                }
                return false;
            }
        }
        return true;
    }
    bool isvalid(vector<vector<char>>& board, int row, int col, char val){
        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;
    }
public:
    void solveSudoku(vector<vector<char>>& board) {
        backtracking(0, 0, board);
    }
};

总结

本题需要很好的理解回溯过程,在本题中如果遇到false,那么就进行上一步的回溯,如果一直没遇到false,就会一直填数字,直到true为止,因此这里也是这题使用bool类型的重要性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值