法1:回溯
想法:
- 遍历数独中每一个空白格,依次填入1~9,每一次填入都要检验其合法性(即行、列、3×3宫不重复),不合法则变回’.’(对当前空白格填入1到9均不合法,则说明前面的有些空白格填错了,回溯),合法则进入下一阶段
- 从上一个填的空白格所在行开始检索(前面的行已经填了),与步骤1相同,依次填入1~9,合法则继续进行下一阶段,不合法则回溯
/**
* @param {character[][]} board
* @return {void} Do not return anything, modify board in-place instead.
*/
var solveSudoku = function(board) {
backtrack(board, 0);
};
function backtrack(board, r) {
var i = r, j = 0, k = 0;
var character = ['1', '2', '3', '4', '5', '6', '7', '8', '9'];
for(; i < 9; i++) {
for(j = 0; j < 9; j++) {
if(board[i][j] == '.') {
for(k = 0; k < 9; k++) {
board[i][j] = character[k];
if(!valid(board, i, j)) {
board[i][j] = '.';
continue;
}
if(!backtrack(board, i)) { // 如果没有合适的数可以满足剩余空格的规则
board[i][j] = '.'; // 回溯,试试下一个数
}
else {
return true;
}
}
if(board[i][j] == '.') { // 1~9 没有合适的数可填入
return false;
}
}
}
}
return true;
}
function valid(board, r, c) {
// 检测填入一个数之后,整个board是否符合条件
// 每行,每列,3×3
var i = 0, j = 0;
var row = [], col = [];
var temp1 = Math.floor(r / 3) * 3, temp2 = Math.floor(c / 3) * 3;
var obj = {'1' : 0, '2' : 0, '3' : 0, '4' : 0, '5' : 0, '6': 0, '7' : 0, '8' : 0, '9' : 0};
// 记录3×3宫中出现的数字的次数
for(i = 0; i < 9; i++) {
row[i] = board[r][i];
col[i] = board[i][c];
}
for(j = 0; j < 9; j++) { // 行,列
if(row[j] != '.') {
if(row.indexOf(row[j], j + 1) > j) {
return false;
}
}
if(col[j] != '.') {
if(col.indexOf(col[j], j + 1) > j) {
return false;
}
}
}
for(i = temp1; i < temp1 + 3; i++) { // 3 × 3的行
for(j = temp2; j < temp2 + 3; j++) { // 3 × 3的列
if(board[i][j] != '.') {
obj[board[i][j]]++;
}
}
}
for(var x in obj) {
if(obj[x] > 1) {
return false;
}
}
return true;
}