连接:
https://leetcode.com/problems/sudoku-solver/#/description
大概题意:
Write a program to solve a Sudoku puzzle by filling the empty cells.
Empty cells are indicated by the character ‘.’.
You may assume that there will be only one unique solution.
解题思路:
此题第一感觉就是使用递归+回溯基本就可以了,开始还以为会超时什么的,大概估算一下每一个格子最多就是9!种情况,应该时间复杂度还好。下面给出代码。
public class Solution {
private static final char[] elems = new char[]{'1','2','3','4','5','6','7','8','9'};//后面方便使用
private char[][]board;//用一个私有变量吧,省得后面传来传去的
public void solveSudoku(char[][] board) {
this.board = board;
solveSudokuHelper(0);//开始从0位置开始就行了,具体看下面代码
}
//下面递归函数,这里把9宫格变成序号的形式,第一行:0~8;第二行9~17;后面依次类推
public boolean solveSudokuHelper(int seqNo){
//格子编号从0~80,如果是81则表示遍历完成,可以返回了,一定是返回true(开始的时候我搞成了void返回类型,导致回溯的时候无法判断是否成功,进而无法判断board中的格子值是要保留还是赋回原值)
if(seqNo==81) return true;
int x = seqNo/9;//将序号转为行号
int y = seqNo%9;//将序号转为列号
//非空直接进行下一个格子
if(this.board[x][y]!='.')
return solveSudokuHelper(seqNo+1);
else{
//如果是空格子,则开始一个个进行尝试
for(int k=0;k<9;k++){
if(check(x,y,elems[k])){
//尝试成功,进行赋值和下一个格子
this.board[x][y] = elems[k];
if(solveSudokuHelper(seqNo+1)){
return true;
}
}
}
//程序能运行到此,表名前面的尝试并没有成功,所以需将x,y位置赋值为'.',并返回false
this.board[x][y]='.';
return false;
}
}
//检查x,y位置是否可以放cur这个值
private boolean check(int x,int y,char cur){
//分别检查行、列、快是否满足
return checkBlockHelper(x,y,cur)&&checkColHelper(x,y,cur)&&checkRowHelper(x,y,cur);
}
/**
*下面分别是对行、列、快的检查函数,很简单不再累赘
*/
private boolean checkRowHelper(int x,int y,char cur){
for(int i=0;i<9;i++){
if((this.board[x][i]-'0')==(cur-'0'))
return false;
}
return true;
}
private boolean checkColHelper(int x,int y,char cur){
for(int i=0;i<9;i++){
if((this.board[i][y]-'0')==(cur-'0'))
return false;
}
return true;
}
private boolean checkBlockHelper(int x,int y,char cur){
int xs = findStartIndex(x);
int ys = findStartIndex(y);
for(int i=xs;i<xs+3;i++){
for(int j=ys;j<ys+3;j++){
if((this.board[i][j]-'0')==(cur-'0'))
return false;
}
}
return true;
}
//找到块的顶点
private int findStartIndex(int x){
return x/3*3;
}
}
运行结果: