乐趣区

leetcode-37-解数独-回溯法模板

在解这道题之前需要了解一下什么是回溯法。

通俗来讲,回溯法就是:当前有多个选择,我们不知道具体要选哪个,就每个都需要尝试。每一个尝试的路径连接起来会得到一个树形解。

比如说上图坐标中的 [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)
};
退出移动版