思路
就按照数独的规则来判断,有三条:
- 横向数字不重复
- 纵向数字不重复
- 3x3 的范围内不重复
循环依然利用深度优先的思路。
代码
➥ JavaScript
/**
* @param {character[][]} board
* @return {boolean}
*/
var isValidSudoku = function(board) {
const boardT = [] // 矩阵转置,用于判断纵向有没有重复
for (let row = 0; row < 9; row++) {
for (let col = 0; col < 9; col++) {
!boardT[col] && (boardT[col] = [])
boardT[col][row] = board[row][col]
}
}
const check = (row, col, num) => {
const r = Math.floor(row / 3)
const c = Math.floor(col / 3)
let block = []
// 将当前元素剔除,以免和自己比较导致失败
board[row][col] = '.'
boardT[col][row] = '.'
// 规则1:判断横向有没有重复数字
if (board[row].indexOf(String(num)) > -1) {
return false
}
// 规则2:判断纵向有没有重复数字
if (boardT[col].indexOf(String(num)) > -1) {
return false
}
// 规则3:判断3x3里面有没有重复数字
for (let i = 0; i < 3; i++) {
block = block.concat([
board[3 * r + i][3 * c],
board[3 * r + i][3 * c + 1],
board[3 * r + i][3 * c + 2]
])
}
if (block.indexOf(num) > -1) {
return false
}
// 恢复当前元素
board[row][col] = num
boardT[col][row] = num
// 顺利冲过三关,返回 true
return true
}
const dfs = row => {
if (row === 9) return true
let flag = true
for (let col = 0; col < 9; col++) {
const num = board[row][col]
if (num === '.') {
continue
} else {
if (!check(row, col, num)) {
flag = false
break // 有一个错误就直接结束判断
}
}
}
return flag ? dfs(row + 1) : false
}
return dfs(0)
}