文章目录
- 1 题目理解
- 2 回溯
1 题目理解
Write a program to solve a Sudoku puzzle by filling the empty cells.
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.
输入:一个字符数组char[][] board。如果这个单元格没有数字,用.表示。
输出:一个数独
规则:每一行,每一列从1到9,每个数只出现一次。每个3x3的方格,从1到9,每个数只出现一次。
2 回溯
对于没有数字的位置,依次尝试1-9的数字,看是否有效。有效则移动位置。思路比较简单,难点在于怎么查找每一行,每一列,每一个方格内数字是否有效。原数组是字符,可以用int类型的数组来表示,查找会更快。int[][] rows表示每一行出现了哪些数字,例如rows[0][3]=1表示第0行数字3已经出现。int[][] cols表示每一列出现了哪些数字。int[][][] boxes 表示第i行第j个方格,哪些数字已经出现。
class Solution {private char[][] board;private int[][] rows;private int[][] cols;private int[][][] boxes;private int n = 9;public void solveSudoku(char[][] board) {this.board = board;rows = new int[n][n+1];cols = new int[n][n+1];boxes = new int[3][3][n+1];for(int i=0;i<n;i++){for(int j=0;j<n;j++){if(board[i][j]!='.'){placeNumber(i,j,board[i][j]-48);}}}dfs(0,0);}private boolean dfs(int i,int j){if(j==n){return true;}int nextI = (i+1)%n;int nextJ = (nextI==0?j+1:j);if(board[i][j] == '.'){for(int d =1;d<=n;d++){if(isValidate(i,j,d)){board[i][j] = (char)(d+'0');placeNumber(i,j,d);if(dfs(nextI,nextJ)){return true;}else{board[i][j] = '.';unPlaceNumber(i,j,d);}}}}else{return dfs(nextI,nextJ);}return false;}private void placeNumber(int i,int j,int d){rows[i][d] = 1;cols[j][d] = 1;boxes[i/3][j/3][d] = 1;}private void unPlaceNumber(int i,int j,int d){rows[i][d] = 0;cols[j][d] = 0;boxes[i/3][j/3][d] = 0;}private boolean isValidate(int i,int j,int d){if(rows[i][d]==1) return false;if(cols[j][d]==1) return false;if(boxes[i/3][j/3][d] == 1) return false;return true;}}