1. 题目描述

编写一个程序,通过已填充的空格来解决数独问题。

一个数独的解法需遵循如下规则:

  • 数字 1-9 在每一行只能出现一次。
  • 数字 1-9 在每一列只能出现一次。
  • 数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。
  • 空白格用 ‘.’ 表示。

37. 解数独 - 图1

一个数独。
37. 解数独 - 图2
答案被标成红色。

Note:

  • 给定的数独序列只包含数字 1-9 和字符 ‘.’ 。
  • 你可以假设给定的数独只有唯一解。
  • 给定数独永远是 9x9 形式的。

    2. 解题思路

    对于这道题目,我们需要对每个格子进行遍历,只要格子为空,就对其进行数字填充,填充数字的过程中要符合规则,根据要求,我们需要对以下两点进行验证:

  • 判断每行每列中的数字不能有重复的值

  • 将整个格子分为九块,分别对其进行验证

对宫格中的格子进行逐行遍历,如果当前的格子满足条件,就遍历下一个格子,下一个若不满足条件,就回溯到上一个格子,进行遍历。如果满足条件,就继续进行遍历。直至遍历完最后一个格子。

3. 代码实现

  1. /**
  2. * @param {character[][]} board
  3. * @return {void} Do not return anything, modify board in-place instead.
  4. */
  5. var solveSudoku = function(board) {
  6. const fn = (row, col,val) => {
  7. // 判断行列中的数是否有冲突,无冲突为false,有冲突为true
  8. for(let i = 0; i < 9; i++){
  9. if(board[i][col] === val || board[row][i] === val){
  10. return true
  11. }
  12. }
  13. const rowStart = Math.floor(row / 3) * 3
  14. const colStart = Math.floor(col / 3) * 3
  15. for(let i = 0; i < 3; i++){
  16. for(let j = 0; j < 3; j++){
  17. if(val === board[rowStart + i][colStart + j]){
  18. return true
  19. }
  20. }
  21. }
  22. return false
  23. }
  24. // 填充board
  25. const fill = (i, j) => {
  26. // 逐行遍历,遍历完一行就换行
  27. if(j === 9){
  28. i ++
  29. j = 0
  30. if(i === 9){
  31. return true
  32. }
  33. }
  34. if(board[i][j] != ".") return fill(i, j + 1) // 递归下一格
  35. for(let num = 1; num <= 9; num++){
  36. if(fn(i, j, String(num))) continue
  37. board[i][j] = String(num)
  38. // 如果基于这个数,填写下一格有解,就返回true,继续执行;如果无解,就将这个还设置为”.“,进行回溯
  39. if(fill(i, j + 1)){
  40. return true
  41. }else{
  42. board[i][j] = "."
  43. }
  44. }
  45. return false
  46. }
  47. fill(0, 0)
  48. return board
  49. };

4. 提交结果

37. 解数独 - 图3