编写一个程序,通过填充空格来解决数独问题。数独的解法需遵循如下规则:数字 1-9 在每一行只能出现一次。数字 1-9 在每一列只能出现一次。数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次数独部分空格内已填入了数字,空白格用 ‘.’ 表示。
回溯法。
时间复杂度:O(1)。
空间复杂度:O(1)。
代码用golang编写。代码如下:
package main
import "fmt"
func main() {
board := [][]byte{
{'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'},
}
solveSudoku(board)
for i := 0; i < len(board); i++ {
for j := 0; j < len(board[0]); j++ {
fmt.Print(fmt.Sprintf("%c\t", board[i][j]))
}
fmt.Println("")
}
}
func solveSudoku(board [][]byte) {
row := make([][]bool, 9)
for i := 0; i < 9; i++ {
row[i] = make([]bool, 10)
}
col := make([][]bool, 9)
for i := 0; i < 9; i++ {
col[i] = make([]bool, 10)
}
bucket := make([][]bool, 9)
for i := 0; i < 9; i++ {
bucket[i] = make([]bool, 10)
}
initMaps(board, row, col, bucket)
process(board, 0, 0, row, col, bucket)
}
func initMaps(board [][]byte, row [][]bool, col [][]bool, bucket [][]bool) {
for i := 0; i < 9; i++ {
for j := 0; j < 9; j++ {
bid := 3*(i/3) + (j / 3)
if board[i][j] != '.' {
num := board[i][j] - '0'
row[i][num] = true
col[j][num] = true
bucket[bid][num] = true
}
}
}
}
// 当前来到(i,j)这个位置,如果已经有数字,跳到下一个位置上
// 如果没有数字,尝试1~9,不能和row、col、bucket冲突
func process(board [][]byte, i int, j int, row [][]bool, col [][]bool, bucket [][]bool) bool {
if i == 9 {
return true
}
// 当离开(i,j),应该去哪?(nexti, nextj)
nexti := twoSelectOne(j != 8, i, i+1)
nextj := twoSelectOne(j != 8, j+1, 0)
if board[i][j] != '.' {
return process(board, nexti, nextj, row, col, bucket)
} else {
// 可以尝试1~9
bid := 3*(i/3) + (j / 3)
for num := 1; num <= 9; num++ { // 尝试每一个数字1~9
if (!row[i][num]) && (!col[j][num]) && (!bucket[bid][num]) {
// 可以尝试num
row[i][num] = true
col[j][num] = true
bucket[bid][num] = true
board[i][j] = byte(num + '0')
if process(board, nexti, nextj, row, col, bucket) {
return true
}
row[i][num] = false
col[j][num] = false
bucket[bid][num] = false
board[i][j] = '.'
}
}
return false
}
}
func twoSelectOne(c bool, a int, b int) int {
if c {
return a
} else {
return b
}
}
执行结果如下: