来解个数独
想+写花了4个小时
主要用的是回溯算法,以及暴力求解
拿到二维数组,先进行一次遍历,记录下所有需要填充数字的位置,存在indexList中,这个list集合中,每一个元素都是需要填充数字的位置的下标(0是行数,1是列数)。
然后再对二维数组进行处理,遍历每个需要填充数字的位置,用一个变量count来记录当前遍历的位置,依次填充1~9进去。没产生冲突,则count的值加1。如果出现冲突(行、列、块的冲突),则需要修改前一位的数(前一位的数字累加1,直到没有冲突),同时使count的值减1,然后再进行当前位置的数的填充。如果前一位的数还产生冲突,就再往前推一个数修改。
代码里标了点注释
class Solution {
List<List<Integer>> indexList = new ArrayList<>();
boolean flag = true;//用于记录最后是否完成填充
int count = 0;
public void solveSudoku(char[][] board) {
process(board);
while(flag) {
choice(board);
//如果count+1小于indexList的大小,说明产生冲突,需要把count位置之后的所有填充数重置,同时下一次进行填充的位置为count对应的位置
int j = count+1;
for(; j < indexList.size(); j++) {
List<Integer> list = indexList.get(j);
if(board[list.get(0)][list.get(1)] == '.') {
break;
}
board[list.get(0)][list.get(1)] = '.';
}
}
}
public void choice(char[][] board) {
while(count < indexList.size()) {
List<Integer> list = indexList.get(count);
int col = list.get(0);
int row = list.get(1);
if(!check(board, col, row)) {
count--;
return;
}
}
//如果遍历indexList中所有的需要填充的位置,都没有发生冲突,则认为填充完成,flag为false,退出solveSudoku方法中的while循环。如果有冲突,则flag不会被置为false,回到solveSudoku方法中的while循环再次进行填充
flag = false;
}
//此方法用于填充数字
public boolean check(char[][] board, int col, int row) {
int temp = '1';
int c = (int)board[col][row];
if(board[col][row] != '.') {
temp = ++c;
}
while(temp < 58) {
//如果产生冲突,就把temp的值+1。直到没有冲突,把temp填充到对应的位置
if(!checkArea(board, col, row, temp)) {
temp++;
continue;
}else {
break;
}
}
if(temp == 58) {
return false;
}
count++;
board[col][row] = (char) temp;
return true;
}
//此方法判断是否产生冲突,需要判断行、列、块的冲突
public boolean checkArea(char[][] board, int col, int row, int temp) {
//块的冲突判断,需要根据行、列的值,算出是哪个块
int colTemp = 0;
int rowTemp = 0;
if(col / 3 > 0) {
colTemp = (col / 3)*3;
}
if(row / 3 > 0) {
rowTemp = (row / 3)*3;
}
int i = colTemp;
for(; i < colTemp+3; i++) {
int j = rowTemp;
for(; j < rowTemp+3; j++) {
if(board[i][j] == temp) {
return false;
}
}
}
for(int j = 0; j < 9; j++) {
if(board[col][j] == temp) {
return false;
}
if(board[j][row] == temp) {
return false;
}
}
return true;
}
//预处理,来得到所有需要填充数字的位置
public void process(char[][] board) {
for(int i = 0; i < 9; i++) {
for(int j = 0; j < 9; j++) {
char c = board[i][j];
if(c == '.') {
List<Integer> tempList = new ArrayList<>();
tempList.add(i);
tempList.add(j);
indexList.add(tempList);
}
}
}
}
}
结果
虽然慢了点