在解这道题之前需要了解一下什么是回溯法。
通俗来讲,回溯法就是:当前有多个选择,我们不知道具体要选哪个,就每个都需要尝试。每一个尝试的路径连接起来会得到一个树形解。
比如说上图坐标中的 [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)};