【每天学习一点算法 2025/11/21】有效数独

每天学习一点算法 2025/11/21

题目:有效数独

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

数字 1-9 在每一行只能出现一次。
数字 1-9 在每一列只能出现一次。
数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。

注意:

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

输入: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

这个问题看似复杂其实一点也不简单,首先啊,这是个二维数组,遍历肯定是要两层循环的。

如果用暴力枚举那肯定也是可以解的,大不了就是遍历每一项,判断当前行、列和 3×3 宫格有没有相同的元素就行了,这里我就不列代码了,有兴趣的朋友可以自己尝试。

那么有没有更优的解题方法呢?

我既然这么问了,那当然是有的了

9×9的数独,我们是不是可以分为 9行、9列、9个3×3的宫格,填满之后都是1~9的数字

我可以先建立三个数组再 push 9个Set集合进去,分别表示行、列和3×3宫格

我们在遍历数独项的时候,遇到非空的项,我就计算一下当前是哪一行、那一列、哪一个3×3宫格,然后判断对应的集合有没有这个数独项,没有的话就添加进去,有的话说明就是一个无效的数独。ok,思路明确上代码。

function isValidSudoku(board: string[][]): boolean {
  const row = Array<Set<string>>()
  const col = Array<Set<string>>()
  const cell = Array<Set<string>>()
  for(var a = 0; a < 9; a++) {
    row.push(new Set())
    col.push(new Set())
    cell.push(new Set())
  }
  for (let i = 0; i < board.length; i++) {
    for (let j = 0; j < board.length; j++) {
      // 计算当前所属3*3宫格
      // 这块可能有一点点绕
      // i 表示行 j表示列 3*3宫格看成整体也就是在一个大的3*3宫格里
      // Math.floor(j / 3) 就表示3*3宫格在第几列
      // Math.floor(i / 3) 就表示3*3宫格在第几行 乘3再加上列 就是当前3*3宫格的索引了
      const k = Math.floor(j / 3) + Math.floor(i / 3) * 3
      // 空项直接跳过
      if (board[i][j] === '.') continue
      // 非空项对应集合有没有对应的项
      const num = board[i][j]
      if (row[i].has(num) || cell[k].has(num)|| col[j].has(num)) {
        return false
      }
      row[i].add(num)
      cell[k].add(num)
      col[j].add(num)
    }
  }
  
  return true
};

题目来源:力扣(LeetCode)

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值