LeetCode 37 解数独 - 回溯解法

LeetCode 37 解数独 - 回溯解法

https://leetcode.cn/problems/sudoku-solver/

思路

一个一个填,而填每个时要检查1-9的合法性(检查合法较为麻烦),然后递归的调用。

错误

for(int i =1;i<=9;i++){
	if(check(board,row,col,i)){
		board[row][col] = i
		write(....) 下一层调用
		board[row][col] = '.'
	}
}

这样是有问题的,到最后没有修改board的值,因为执行完 write 函数后,立即会又改为 . ,这样到最后 board 又被修改回去了,错误的代码如下:

class Solution {

public:

    bool check(vector<vector<char>>& board, int row, int col, int num) {

        for (int i = 0; i < 9; i++) {

            // 行:row 列:i

            if (board[row][i] - '0' == num)

                return false;

        }

        for (int i = 0; i < 9; i++) {

            if (board[i][col] - '0' == num)

                return false;

        }

        for (int i = (row / 3) * 3; i < (row / 3) * 3 + 3; i++) {

            for (int j = (col / 3) * 3; j < (col / 3) * 3 + 3; j++) {

                if (board[i][j] - '0' == num)

                    return false;

            }

        }

        return true;

    }

    void write(vector<vector<char>>& board, int row, int col) {

        if (row == 9)

            return;

        if (board[row][col] == '.') {

            for (int i = 1; i <= 9; i++) {

                if (check(board, row, col, i)) {

                    board[row][col] = (char)(i + '0');

                    write(board, row + 1, (col + 1) % 9);//这里row和col计算不对

                    board[row][col] = '.';

                }

            }

        }

        else{

            write(board, row + 1, (col + 1) % 9);

        }

    }

    void solveSudoku(vector<vector<char>>& board) { write(board, 0, 0); }

};

改正

我们要做的就是,在得到合法状态后,不要执行后面的 board[row][col] = '.'; ,所以需要 return, 这就需要下层调用向上返回是否找到合法状态

返回 true 表示找到合法状态, 这时直接return,不执行后面的 board[row][col] = '.'

for(int i =1;i<=9;i++){
	if(check(board,row,col,i)){
		board[row][col] = i
		if(write(....) 下一层调用) return;
		board[row][col] = '.'
	}
}
小插曲: 我的代码计算 next_row next_col 有误,正确的应该是 在列到8时 row 要加一。只用取余函数是不对的。

代码

class Solution {

public:

    bool check(vector<vector<char>>& board, int row, int col, int num) {

        for (int i = 0; i < 9; i++) {

            // 行:row 列:i

            if (board[row][i] - '0' == num)

                return false;

        }

        for (int i = 0; i < 9; i++) {

            if (board[i][col] - '0' == num)

                return false;

        }

        for (int i = (row / 3) * 3; i < (row / 3) * 3 + 3; i++) {

            for (int j = (col / 3) * 3; j < (col / 3) * 3 + 3; j++) {

                if (board[i][j] - '0' == num)

                    return false;

            }

        }

        return true;

    }

    bool write(vector<vector<char>>& board, int row, int col) {

        if (row == 9)

            return true;

        int next_row = col==8?row+1:row;

        int next_col = (col + 1) % 9;

        if (board[row][col] == '.') {

            for (int i = 1; i <= 9; i++) {

                if (check(board, row, col, i)) {

                    board[row][col] = (char)(i + '0');

                    if (write(board, next_row, next_col)) {

                        return true;

                    };

                    board[row][col] = '.';

                }

            }

            return false;

        } else {

            return write(board, next_row, next_col);

        }

    }

    void solveSudoku(vector<vector<char>>& board) { write(board, 0, 0); }

};