LeetCode 题解 | 37. 解数独(bool型DFS C++)

题目描述(困难难度)

原题链接
在这里插入图片描述

算法

(DFS) O ( ( 9 ! ) 9 ) O((9!)^9)

  • 枚举每个点,如果是空格,就选择合适的点进行填数,然后不断往下搜索,直到填完所有数(x == n)时,dfs从里不断返回true,直到退到最外面的递归函数位置
  • 这里bool型dfs的好处是可以防止找到一种方案了,还去恢复现场
  • 注意:这里不同于n皇后问题,这里是修改原数组(修改成一种可行解即可),而皇后问题是输出结果,不是修改原数组

bool型dfs递归函数的核心是 if (dfs(参数)) return true;

时间复杂度是 O ( ( 9 ! ) 9 ) O((9!)^9)

  • 第一行的格子最多有9!种可能
  • 第二行的格子最多有8*7…*1=8!种可能
  • 第三行的格子最多有7*6…*1=7!种可能

所以不管怎么样,最多也就 ( 9 ! ) 9 (9!)^9 次操作

C++代码

class Solution {
public:
    // row[x][u]表示第x行是否已经填过数字u(0-8)
    // col[y][u]表示第y行是否已经填过数字u(0-8)
    // box[x / 3][y / 3][u]表示第[x/3,y/3]个box是否已经填过数字u(0-8)

    bool row[9][9] = {0}, col[9][9] = {0}, cell[3][3][9] = {0};
    void solveSudoku(vector<vector<char>>& board) {
        for (int i = 0; i < 9; i ++ ) {
            for (int j = 0; j < 9; j ++ ) {
                char c = board[i][j];
                if (c != '.') {
                    int u = c - '1'; // u: '1' - '1' = 0
                    row[i][u] = col[j][u] = cell[i / 3][j / 3][u] = true;
                }
            }
        }

        dfs(board, 0, 0);
    }

    bool dfs(vector<vector<char>>& board, int x, int y) {
        if (y == 9) x ++ , y = 0; // 先改变
        if (x == 9) return true; // 填完所有格子,返回true

        if (board[x][y] != '.') return dfs(board, x, y + 1);
        
        for (int i = 0; i < 9; i ++ ) {
            if (!row[x][i] && !col[y][i] && !cell[x / 3][y / 3][i]) {
                board[x][y] = i + '1';
                row[x][i] = col[y][i] = cell[x / 3][y / 3][i] = true;

                // 如果下面搜索后是对的,就提前返回,不恢复现场(因为要修改board);
                // 如果是false就恢复现场(这个方法很巧妙)
                if (dfs(board, x, y + 1)) return true; 
                board[x][y] = '.';
                row[x][i] = col[y][i] = cell[x / 3][y / 3][i] = 0;

            }
        }
        return false;
    }
};

未用bool型dfs会显得很麻烦,效率低下

440 ms 91.4 MB

class Solution {
public:
    bool col[9][10], row[9][10], box[3][3][10];
    int n, m;
    
    void dfs(int x, int y, vector<vector<char>> tmp, vector<vector<char>> & board) {
        if (y == 9) x ++, y = 0;
        if (x == 9) { // 皇后问题是在这输出结果
            for (int i = 0; i < n; i ++) {
                for (int j = 0; j < m; j ++) {
                    board[i][j] = tmp[i][j];
                }
            }
            return;
        }

        if (tmp[x][y] != '.') dfs(x , y + 1, tmp, board);
        else { // 填数
            for (int i = 1; i <= 9; i ++) {
                if (!col[x][i] && !row[y][i] && !box[x / 3][y / 3][i]) {
                    tmp[x][y] = i + '0';
                    col[x][i] = row[y][i] = box[x / 3][y / 3][i] = true;
                    dfs(x, y + 1,tmp, board);
                    col[x][i] = row[y][i] = box[x / 3][y / 3][i] = false; // 恢复现场
                    tmp[x][y] = '.';
                }
            }
        }
        return;

    }

    void solveSudoku(vector<vector<char>>& board) {
        n = board.size(), m = board[0].size();

        for (int x = 0; x < n; x ++) {
            for (int y = 0; y < m; y ++) {
                if (board[x][y] != '.') {
                    int i = board[x][y] - '0'; // i:1-9
                    col[x][i] = row[y][i] = box[x / 3][y / 3][i] = true;
                }
            }
        }

        dfs(0, 0, board, board);
        return;
    }
};

写在最后:我的博客主要是对计算机领域所学知识的总结、回顾和思考,把每篇博客写得通俗易懂是我的目标,分享技术和知识是一种快乐 ,非常欢迎大家和我一起交流学习,有任何问题都可以在评论区留言,也期待与您的深入交流(^∀^●)

发布了248 篇原创文章 · 获赞 89 · 访问量 10万+

猜你喜欢

转载自blog.csdn.net/qq_43827595/article/details/104364234