在解这道题之前需要了解一下什么是回溯法。
通俗来讲,回溯法就是:当前有多个选择,我们不知道具体要选哪个,就每个都需要尝试。每一个尝试的路径连接起来会得到一个树形解。
比如说上图坐标中的 [0,2]
这个位置,通过观察,我们可以知道这个位置可以放置的数字有:1、2、4
,如果我们当前位置选择放置 1
,则下一个位置能够选择放置的数字有:2、6
,如果我们当前位置选择放置 2
,则下一个位置能够选择放置的数字有:1、6
。通过分析可以画出树形解:
37. 解数独 题解
/**
* @param {character[][]} board
* @return {void} Do not return anything, modify board in-place instead.
*/
var solveSudoku = function(board) {
// 辅助函数,判断当前位置放置某个值是否可行
function isOk(i,j,val){
// 判断当前行是否已存在该数
for(let k = 0; k<9; k++){if(board[i][k] == val) return false
}
// 判断当前列是否已存在该数
for(let k = 0; k<9; k++){if(board[k][j] == val) return false
}
// 判断当前的 3 * 3 格中是否已存在该数
let l = Math.floor(j/3)*3, t = Math.floor(i/3)*3
for(let m = t; m < t+3; m++){for(let n = l; n < l+3; n++){if(board[m][n] == val) return false
}
}
return true
}
function backTrace(i,j){if(j === 9){
// 数独已结完,返回 true
if(i === 8) return true
// 否则进入下一行
i++
j = 0
}
// 当前位置没有填数字
if(board[i][j] === '.'){
// 从 1-9 中选择满足条件的数填入
for(let val = 1; val<=9; val++){
// 如果当前数字满足条件,写入数独中
if(isOk(i,j,val)){board[i][j] = val + ''
// 这条路径上如果有解,则满足条件直接返回
if(backTrace(i,j+1)) return true
}
board[i][j] = '.'
}
}else{
// 当前位置有数字,直接进入下一格
return backTrace(i,j+1)
}
// 如果当前格既没有数字,也没有满足条件的数字能填入,// 说明这条路径不通
return false
}
backTrace(0,0)
};