题目:
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-9must occur exactly once in each row. - Each of the digits
1-9must occur exactly once in each column. - Each of the the digits
1-9must occur exactly once in each of the 93x3sub-boxes of the grid.
Empty cells are indicated by the character '.'.
![]()
A sudoku puzzle...
![]()
...and its solution numbers marked in red.
Note:
- The given board contain only digits
1-9and the character'.'. - You may assume that the given Sudoku puzzle will have a single unique solution.
- The given board size is always
9x9.
题意:
该题题意理解起来很简单,就是做一个9x9的数独题,每行每列只出现1-9数字各一次,每个小九宫格出现1-9数字各一次。
题目中,给定输入,数独表中空缺的填入字符'.'。
解法:
思路是运用深度优先遍历加上回溯法来进行解答。将整个9x9的表看成81个点的序列,由第一个点出发,寻找可以填入的值(遇到表中固定值时跳过),一步一步进行,如果遇到无法走通的地方,进行回溯。一直进行以上操作,直到走到81格。
非递归:
class Solution {
public void solveSudoku(char[][] board) {
int d=0,k=0,row=0,col=0,start=0;
int []flag=new int[81];
for(int i=0;i<9;i++){
for(int j=0;j<9;j++){
if(board[i][j]=='.') flag[k]=1;
else flag[k]=0;
k++;
}
}
while(d<81){
if(flag[d]==0) {
d++;
continue;
}
row=d/9;
col=d%9;
if(board[row][col]=='.'){
start=1;
}
else{
start=board[row][col]-'0'+1;
}
for(k=start;k<=9;k++){
if(valid(board,row,col,(char)(k+'0'))==true) break;
}
if(k==10){ //回溯
board[row][col]='.';
for(int h=d-1;h>=0;h--){
if(flag[h]==1) {
d=h;
break;
}
}
}
else{
board[row][col]=(char)(k+'0');
d++;
}
}
}
public static boolean valid(char[][] board,int i,int j,char temp){ //判断填入值是否有效
for(int x=0;x<9;x++){
if(board[i][x]==temp||board[x][j]==temp) return false;
}
int bi=i/3;
int bj=j/3; //计算属于哪个小九宫格
for(int x=bi*3;x<bi*3+3;x++){
for(int y=bj*3;y<bj*3+3;y++){
if(board[x][y]==temp) return false;
}
}
return true;
}
}
递归法:
public class Solution {
public void solveSudoku(char[][] board) {
dfs(board,0);
}
private boolean dfs(char[][] board, int d) {
if (d==81) return true; //found solution
int i=d/9, j=d%9;
if (board[i][j]!='.') return dfs(board,d+1);//prefill number skip
boolean[] flag=new boolean[10];
validate(board,i,j,flag);
for (int k=1; k<=9; k++) {
if (flag[k]) {
board[i][j]=(char)('0'+k);
if (dfs(board,d+1)) return true;
}
}
board[i][j]='.'; //if can not solve, in the wrong path, change back to '.' and out
return false;
}
private void validate(char[][] board, int i, int j, boolean[] flag) {
Arrays.fill(flag,true);
for (int k=0; k<9; k++) {
if (board[i][k]!='.') flag[board[i][k]-'0']=false;
if (board[k][j]!='.') flag[board[k][j]-'0']=false;
int r=i/3*3+k/3;
int c=j/3*3+k%3;
if (board[r][c]!='.') flag[board[r][c]-'0']=false;
}
}
}
本文介绍了一种使用深度优先搜索和回溯法解决数独问题的算法。通过将数独视为81个点的序列,从第一个点开始,寻找合法的填数字位置,遇到障碍则回溯,直至找到解决方案。
2982

被折叠的 条评论
为什么被折叠?



