LeetCode 37. 解数独

描述

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

一个数独的解法需遵循如下规则:
数字 1-9 在每一行只能出现一次。
数字 1-9 在每一列只能出现一次。
数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。

空白格用 ‘.’ 表示。

LeetCode 37. 解数独

一个数独。

LeetCode 37. 解数独

答案被标成红色。

提示:

  • 给定的数独序列只包含数字 1-9 和字符 ‘.’ 。
  • 你可以假设给定的数独只有唯一解。
  • 给定数独永远是 9x9 形式的。

思路

  • 这道题做了一天没解出来…哎,好难,最终还是看了答案。
  • 解数独是回溯算法的经典应用。这道题要注意题设一点:答案唯一。也就是说,回溯时只要找到一个答案,程序就可以结束了。为了达到此目的,将回溯函数返回值设为bool,当找到答案时返回true,不再继续递归。
  • 从第0行0列开始遍历,先遍历第0行的每一列,然后遍历第1行的每一列…如此直到row=9时超出网格范围,递归结束。
  • 对于某些网格,如果为空,才从1~9开始遍历往里填,如果已经有值了,那么直接跳过此格子,进入本行的下一个格子。
  • 需要写一个函数,判断当前格子的同行、同列,本宫(3x3格子)内是否已经有此元素,没有才能放,有的话跳过。

解答

class Solution {
public:
    void solveSudoku(vector<vector<char>>& board) {
        backTrack(board, 0, 0);//从第0行0列开始递归
    }

    bool backTrack(vector<vector<char>>& board, int row, int column){
        if(row == 9) return true;//row=9说明找到了正确结果
        
        if(column == 9)
            return backTrack(board, row + 1, 0);//column=9,则开始下一行,必须return,否则下面代码还会执行
        
        if(board[row][column] == '.'){
            for(char i = '1';i <= '9'; ++ i){
                if(isInBoard(board, row, column, i) == false){//当前数可填入
                    board[row][column] = i;
                    if(backTrack(board, row, column + 1)) return true;//找到结果,结束程序
                    board[row][column] = '.';
                } 
            }
        }else{
            //本层得到后续递归的结果抛给上一层,不return会执行下面的return false,将false抛给上层
            return backTrack(board, row, column + 1);
        }
        return false;//能执行到这步,说明遍历完1~9也没找到合适的数,则失败。
    }

    //查找某个数是否已经在本行、本列、本宫内存在,已存在则返回true
    bool isInBoard(vector<vector<char>>& board, int row, int column, char target){
        for(int k = 0;k < 9; ++ k){
            if(board[row][k] == target || board[k][column] == target ||
                board[(row / 3) * 3 + k / 3][(column / 3) * 3 + k % 3] == target) 
                return true;
        }
        return false;
    }
};
上一篇:面试题 08.04. 幂集


下一篇:NC121—字符串的排列