37. Sudoku Solver

问题:

数独问题,给定一个数独数组,求解填入数字,有且只有一个解。

A sudoku solution must satisfy all of the following rules:

Each of the digits 1-9 must occur exactly once in each row.
Each of the digits 1-9 must occur exactly once in each column.
Each of the digits 1-9 must occur exactly once in each of the 9 3x3 sub-boxes of the grid.
The '.' character indicates empty cells.

Example 1:
Input: board = [["5","3",".",".","7",".",".",".","."],["6",".",".","1","9","5",".",".","."],[".","9","8",".",".",".",".","6","."],["8",".",".",".","6",".",".",".","3"],["4",".",".","8",".","3",".",".","1"],["7",".",".",".","2",".",".",".","6"],[".","6",".",".",".",".","2","8","."],[".",".",".","4","1","9",".",".","5"],[".",".",".",".","8",".",".","7","9"]]
Output: [["5","3","4","6","7","8","9","1","2"],["6","7","2","1","9","5","3","4","8"],["1","9","8","3","4","2","5","6","7"],["8","5","9","7","6","1","4","2","3"],["4","2","6","8","5","3","7","9","1"],["7","1","3","9","2","4","8","5","6"],["9","6","1","5","3","7","2","8","4"],["2","8","7","4","1","9","6","3","5"],["3","4","5","2","8","6","1","7","9"]]
Explanation: The input board is shown above and the only valid solution is shown below.

Constraints:
board.length == 9
board[i].length == 9
board[i][j] is a digit or '.'.
It is guaranteed that the input board has only one solution.

37. Sudoku Solver    ->    37. Sudoku Solver

解法:Backtracking(回溯算法)

参数:

  • path:board到目前为止填入的情况。
      • pos:当前位置 i,j
  • optionlists:1~9。(除去不合要求的数字,使用isValid进行check)

处理:

    • 退出条件:if(遍历到9*9最后一个格子之后) 则标记已找到答案find=true,return
    • for所有可选项:opt=1~9 &&( isValid == true )
  • 做选择:board[i][j]=opt
  • 递归:
    • backtracking(board, pos+1) 
  • 撤销选择:board[i][j]='.'

⚠️ 特别的,isValid的判断方法:board中:

  • 在同一行中,没有冲突(与要填入的opt重复)
  • 在同一列中,没有冲突(与要填入的opt重复)
  • 在同一小方块中,没有冲突(与要填入的opt重复)
    • 找到所在小方块的↖️左上坐标:row=i-i%3, col=j-j%3

 

代码参考:

 1 class Solution {
 2 public:
 3     bool find=false;
 4     void solveSudoku(vector<vector<char>>& board) {
 5         backtracking(board, 0);
 6     }
 7 
 8     void backtracking(vector<vector<char>>& board, int pos) {
 9         while(pos<(9*9) && board[pos/9][pos%9] != '.') pos++;
10         if(pos==(9*9)) {
11             find=true;
12             return;
13         }
14         int i = pos/9, j = pos%9;
15         for(char opt='1'; opt<='9'; opt++) {
16             if(isValid(board, i, j, opt)) {
17                 board[i][j] = opt;
18                 backtracking(board, pos+1);
19                 if(find) return;
20                 board[i][j] = '.';
21             }
22         }
23         return;
24     }
25     bool isValid(const vector<vector<char>>& board, int i, int j, char opt) {
26         if(isRowConflict(board, i, j, opt)) return false;
27         if(isColConflict(board, i, j, opt)) return false;
28         if(isRecConflict(board, i, j, opt)) return false;
29         return true;
30     }
31     
32     bool isRowConflict(const vector<vector<char>>& board, int i, int j, char opt) {
33         for(int jt = 0; jt < 9; jt++) {
34             if(board[i][jt] == opt) return true;
35         }
36         return false;
37     }
38     bool isColConflict(const vector<vector<char>>& board, int i, int j, char opt) {
39         for(int it = 0; it < 9; it++) {
40             if(board[it][j] == opt) return true;
41         }
42         return false;
43     }
44     bool isRecConflict(const vector<vector<char>>& board, int i, int j, char opt) {
45         int row = i-i%3;
46         int col = j-j%3;//evey Rec ↖︎leftup cell pos
47         for(int it = 0; it < 3; it++) {
48             for(int jt = 0; jt < 3; jt++) {
49                 if(board[row+it][col+jt] == opt) return true;
50             }
51         }
52         return false;
53     }
54 };

 

上一篇:机器学习之线性判别分析LDA


下一篇:Ceres-Solver学习日志:自动求导使用样例