126、【回溯算法】leetcode ——37. 解数独:三维信息判定(C++版本)

题目描述

126、【回溯算法】leetcode ——37. 解数独:三维信息判定(C++版本)_第1张图片
126、【回溯算法】leetcode ——37. 解数独:三维信息判定(C++版本)_第2张图片
126、【回溯算法】leetcode ——37. 解数独:三维信息判定(C++版本)_第3张图片
126、【回溯算法】leetcode ——37. 解数独:三维信息判定(C++版本)_第4张图片
126、【回溯算法】leetcode ——37. 解数独:三维信息判定(C++版本)_第5张图片
原题链接:37. 解数独

解题思路

本题的难点有两个:
(1)按哪种方式去回溯遍历?
(2)如何去确定填充符合要求?

解决方法:
(1)按照9×9的for循环遍历,遇到'.'就判定是否可填充,如果可以则填充
(2)判定行是否有冲突,判定列是否有冲突,判定3x3的小单元内是否有冲突(这也是本题判定的难点)

class Solution {
public:
    // 判定是否行、列、格内所填数符合规定
    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;
        }

        // 判定3x3的小单元个内是否有重复
        // 先除三,可分类出在第1个、第2个还是3个小单元。再乘3,可保证从每个小单元的起始位置开始遍历
        int startRow = (row / 3) * 3, 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;
    }

    bool backtracking(vector<vector<char>>& board) {
        for(int i = 0; i < 9; i++) {
            for(int j = 0; j < 9; j++) {
                if(board[i][j] == '.') {                            // 当遍历到此位置没有填数
                    for(char ch = '1'; ch <= '9'; ch++) {           // 枚举9个数尝试填入
                        if(isValid(board, i, j, ch)) {
                            board[i][j] = ch;
                            bool res = backtracking(board);
                            if(res == true)         return true;    // 当后续的所有数都正确填入,直接返回
                            board[i][j] = '.';                      // 未成功填入,则回溯枚举下一种情况
                        }
                    }                                        
                    return false;                                   // 枚举后都没有可以正确填充的,则返回false
                }                
            }
        }
        return true;                                                // 都已被填充完,则返回true
    }
    void solveSudoku(vector<vector<char>>& board) {
        backtracking(board);
    }
};

参考文章:37. 解数独

你可能感兴趣的:(数据结构与算法刷题,#,回溯算法,算法,leetcode,c++)