📑 题目:37. 解数独

🚀 本题 LeetCode 传送门

题目大意

编写一个程序,通过已填充的空格来解决数独问题。一个数独的解法需遵循如下规则:

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

空白格用 ‘.’ 表示。

解题思路

  • 给出一个数独谜题,要求解出这个数独
  • 解题思路 DFS 暴力回溯枚举。数独要求每横行,每竖行,每九宫格内,1-9 的数字不能重复,每次放下一个数字的时候,在这 3 个地方都需要判断一次。
  • 另外找到一组解以后就不需要再继续回溯了,直接返回即可。

代码

  1. package leetcode
  2. type position struct {
  3. x int
  4. y int
  5. }
  6. func solveSudoku(board [][]byte) {
  7. pos, find := []position{}, false
  8. for i := 0; i < len(board); i++ {
  9. for j := 0; j < len(board[0]); j++ {
  10. if board[i][j] == '.' {
  11. pos = append(pos, position{x: i, y: j})
  12. }
  13. }
  14. }
  15. putSudoku(&board, pos, 0, &find)
  16. }
  17. func putSudoku(board *[][]byte, pos []position, index int, succ *bool) {
  18. if *succ == true {
  19. return
  20. }
  21. if index == len(pos) {
  22. *succ = true
  23. return
  24. }
  25. for i := 1; i < 10; i++ {
  26. if checkSudoku(board, pos[index], i) && !*succ {
  27. (*board)[pos[index].x][pos[index].y] = byte(i) + '0'
  28. putSudoku(board, pos, index+1, succ)
  29. if *succ == true {
  30. return
  31. }
  32. (*board)[pos[index].x][pos[index].y] = '.'
  33. }
  34. }
  35. }
  36. func checkSudoku(board *[][]byte, pos position, val int) bool {
  37. // 判断横行是否有重复数字
  38. for i := 0; i < len((*board)[0]); i++ {
  39. if (*board)[pos.x][i] != '.' && int((*board)[pos.x][i]-'0') == val {
  40. return false
  41. }
  42. }
  43. // 判断竖行是否有重复数字
  44. for i := 0; i < len((*board)); i++ {
  45. if (*board)[i][pos.y] != '.' && int((*board)[i][pos.y]-'0') == val {
  46. return false
  47. }
  48. }
  49. // 判断九宫格是否有重复数字
  50. posx, posy := pos.x-pos.x%3, pos.y-pos.y%3
  51. for i := posx; i < posx+3; i++ {
  52. for j := posy; j < posy+3; j++ {
  53. if (*board)[i][j] != '.' && int((*board)[i][j]-'0') == val {
  54. return false
  55. }
  56. }
  57. }
  58. return true
  59. }