GH1995 / leetcode-test-and-run

方便 leetcode 刷题的小工具
GNU General Public License v2.0
0 stars 0 forks source link

37. Sudoku Solver 求解数独 #6

Open GH1995 opened 5 years ago

GH1995 commented 5 years ago

37. Sudoku Solver

Difficulty: Hard

Write a program to solve a Sudoku puzzle by filling the empty cells.

A sudoku solution must satisfy all of the following rules:

  1. Each of the digits 1-9 must occur exactly once in each row.
  2. Each of the digits 1-9 must occur exactly once in each column.
  3. Each of the the digits 1-9 must occur exactly once in each of the 9 3x3 sub-boxes of the grid.

Empty cells are indicated by the character '.'.


A sudoku puzzle...


...and its solution numbers marked in red.

Note:

Solution

Language: C++

class Solution {
 public:
  void solveSudoku(vector<vector<char>>& board) {
    if (board.empty() || board.size() != 9 || board.front().size() != 9) return;
    dfs(board, 0, 0);
  }

  bool dfs(vector<vector<char>>& board, int i, int j) {
    if (i == 9) return true;                  // 临界条件
    if (j >= 9) return dfs(board, i + 1, 0);  // 状态转换

    // 两种扩展
    if (board[i][j] == '.') {
      for (int k = 1; k <= 9; ++k) {
        board[i][j] = k + '0';

        if (isValid(board, i, j))
          if (dfs(board, i, j + 1))  // 相信 i,j+1也合法,信任链
            return true;

        board[i][j] = '.'; // 恢复原状
      }
    } else {
      return dfs(board, i, j + 1);
    }
    return false;
  }

  bool isValid(vector<vector<char>>& board, int i, int j) { // 这里检查的是 j
    for (int col = 0; col < 9; ++col) {  // 检查列
      if (col != j && board[i][j] == board[i][col]) return false;
    }

    for (int row = 0; row < 9; ++row) {  // 检查行
      if (row != i && board[i][j] == board[row][j]) return false;
    }

    for (int row = i / 3 * 3; row < i / 3 * 3 + 3; ++row)  // 检查单元格
      for (int col = j / 3 * 3; col < j / 3 * 3 + 3; ++col) {
        if ((row != i || col != j) && board[i][j] == board[row][col])
          return false;
      }

    return true;
  }
};
GH1995 commented 5 years ago

return的是信任链

对于每个需要填数字的格子带入1到9,每代入一个数字都判定其是否合法,如果合法就继续下一次递归,结束时把数字设回'.',判断新加入的数字是否合法时,只需要判定当前数字是否合法,不需要判定这个数组是否为数独数组,因为之前加进的数字都是合法的,这样可以使程序更加高效一些