LeetCode36、有效的数独

83 阅读3分钟

LeetCode 系列记录我学习算法的过程。

持续创作,加速成长!这是我参与「掘金日新计划 6 月更文挑战」的第 30 天,点击查看活动详情

题目

请你判断一个 9 x 9 的数独是否有效。只需要 根据以下规则 ,验证已经填入的数字是否有效即可。

数字 1-9 在每一行只能出现一次。 数字 1-9 在每一列只能出现一次。 数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。(请参考示例图)

注意:

  • 一个有效的数独(部分已被填充)不一定是可解的。
  • 只需要根据以上规则,验证已经填入的数字是否有效即可。
  • 空白格用 '.' 表示。

示例:

image.png

输入:board = 
[["5","3",".",".","7",".",".",".","."]
,["6",".",".","1","9","5",".",".","."]
,[".","9","8",".",".",".",".","6","."]
,["8",".",".",".","6",".",".",".","3"]
,["4",".",".","8",".","3",".",".","1"]
,["7",".",".",".","2",".",".",".","6"]
,[".","6",".",".",".",".","2","8","."]
,[".",".",".","4","1","9",".",".","5"]
,[".",".",".",".","8",".",".","7","9"]]
输出:true



输入:board = 
[["8","3",".",".","7",".",".",".","."]
,["6",".",".","1","9","5",".",".","."]
,[".","9","8",".",".",".",".","6","."]
,["8",".",".",".","6",".",".",".","3"]
,["4",".",".","8",".","3",".",".","1"]
,["7",".",".",".","2",".",".",".","6"]
,[".","6",".",".",".",".","2","8","."]
,[".",".",".","4","1","9",".",".","5"]
,[".",".",".",".","8",".",".","7","9"]]
输出:false
解释:除了第一行的第一个数字从 5 改为 8 以外,空格内其他数字均与 示例1 相同。 
但由于位于左上角的 3x3 宫内有两个 8 存在, 因此这个数独是无效的。

提示

  • board.length == 9
  • board[i].length == 9
  • board[i][j] 是一位数字(1-9)或者 '.'

思路

这是类似数独的题目,但是除了每一行和每一列不能有重复数字外,还多了一个要求,即每一个3 * 3宫格内也不允许重复

我们可以通过循环的形式来遍历所有元素,通过三个变量分别存储行列及宫格元素,有重复返回 false,遍历完则返回 true

  • 首先定义 row 存储当前行的非空元素,column 存储每一列的非空元素,box 存储每个宫格的非空元素
  • 双重循环进行遍历,外层 x 遍历行,内层 y 遍历列
  • 每次遍历行时,将 row 置空以存储当前行的元素,columnbox 不需要置空
  • 获取当前元素值 cur,仅当 cur 不为 . 才进行操作
  • 首先进行当前行元素的判断处理,如果 row 存在当前元素,返回 false ,反之将其存储在 row
  • 然后判断 column 中是否有当前列 y 的数据,无则创建列 y 并存入 cur,有则判断列 y 中是否存在 cur,存在返回 false,反之将其存入列 y
  • 最后判断宫格,总共有 9 个宫格,对应下标可通过 Math.floor(x / 3) * 3 + Math.floor(y / 3) 获取
  • 宫格里数据的判断同列的判断一致
  • 所有元素都遍历完,则返回 true

代码实现

/**
 * @param {character[][]} board
 * @return {boolean}
 */
var isValidSudoku = function(board) {

    let row, column = new Map(), box = new Map()
    for(let x = 0; x < 9; x++) {
        row = new Map()
        for(let y = 0; y < 9; y++) {
            const cur = board[x][y]
            if(cur !== '.') {
                // 行
                if (row.has(cur)) {
                    return false
                } else {
                    row.set(cur, true)
                }

                // 列
                if (column.has(y)) {
                    if (column.get(y).has(cur)) {
                        return false
                    } else {
                        column.get(y).set(cur, true)
                    }
                } else {
                    column.set(y, new Map([[cur, true]]))
                }

                // 宫格
                const idx = Math.floor(x / 3) * 3 + Math.floor(y / 3)
                if (box.has(idx)) {
                    if (box.get(idx).has(cur)) {
                        return false
                    } else {
                        box.get(idx).set(cur, true)
                    }
                } else {
                    box.set(idx, new Map([[cur, true]]))
                }
            }
        }
    }

    return true
};

image.png