2021-09-23:编写一个程序,通过填充空格来解决数独问题。数独的解法需遵循如下规则:数字 1-9 在每一行只能出现一次。数字 1-9 在每一列只能出现一次。数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次数独部分空格内已填入了数字,空白格用 '.' 表示。
福大大 答案2021-09-23:
回溯法。
时间复杂度: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 } }
执行结果如下: