问题:
数独问题,给定一个数独数组,求解填入数字,有且只有一个解。
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.
->
解法: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 };