Files
leetcode-master/problems/0037.解数独.md
youngyangyang04 4ebcfbbc81 Update
2020-09-15 09:58:22 +08:00

2.7 KiB
Raw Blame History

题目地址

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

思路

棋盘搜索问题依然是要使用回溯法,暴力搜索,只不过这次我们要做的是双层递归。

怎么做双层递归呢如果大家之前做过回溯类型的题目例如77.组合组合问题131.分割回文串分割问题78.子集子集问题46.全排列排列问题以及51.N皇后N皇后问题等等都会发现这些都是单层递归。

如果大家以上这几道题目没有做过的话,不建议上来就做这道题哈!

n皇后因为每一行每一列只放一个皇后只需要一层for循环遍历行数递归来处理每一行的一个皇后放在哪里就可以。

本题就不一样了本题中棋盘每一个位置都要放一个数字这个问题的树形结构要比N皇后更宽更深。

如图所示:

可以看出我们需要的是一个二维的递归也就是两个for循环递归遍历每一个棋盘的位置

这道题目和之前递归的方式都不一样,这里相当于两层递归,之前的都是一层递归。

C++代码

class Solution {
private:
bool backtracking(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] != '.') continue;
            for (char k = '1'; k <= '9'; k++) { // (i, j) 这个位置放k是否合适
                if (isValid(i, j, k, board)) { 
                    board[i][j] = k;
                    if (backtracking(board)) return true; // 如果找到合适一组立刻返回
                    board[i][j] = '.';
                }
            }
            return false;
        }
    }
    return true; // 遍历完没有返回false说明找到了合适棋盘位置了

}
bool isValid(int row, int col, char val, vector<vector<char>>& board) {

    for (int i = 0; i < 9; i++) { // 判断行里是否重复
        if (board[row][i] == val) {
            return false;
        }
    }
    for (int j = 0; j < 9; j++) { // 判断列里是否重复
        if (board[j][col] == val) {
            return false;
        }
    }
    int startRow = (row / 3) * 3;
    int startCol = (col / 3) * 3;
    for (int i = startRow; i < startRow + 3; i++) { // 判断9方格里是否重复
        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(board);
    }
};