1. 程式人生 > 實用技巧 >leetcode刷題-37解數獨

leetcode刷題-37解數獨

題目

編寫一個程式,通過已填充的空格來解決數獨問題。

一個數獨的解法需遵循如下規則:

數字1-9在每一行只能出現一次。
數字1-9在每一列只能出現一次。
數字1-9在每一個以粗實線分隔的3x3宮內只能出現一次。
空白格用'.'表示。

思路

使用暴力破解是不現實的,其需要9^81次運算。

因此與數獨相同,都需要用到回溯的思想。

其演算法可以簡化為:

1.從頭開始選擇到一個空白格

2.選擇數字1-9中的一個,判斷是否符合標準(不能重複出現在行,列,3*3方格中)

  2.1 填入數字

  2.2 檢查其是否已經找出了數獨的解

    2.2.1 若抵達最後一格,獲得數獨的解

    2.2.2 若沒有抵達最後一格,放置下一個數字

    2.2.3 若不存在解,刪除當前數字

實現

class Solution:
    def solveSudoku(self, board: List[List[str]]) -> None:
        """
        Do not return anything, modify board in-place instead.
        """
        flag = False
        line = [[]for i in range(9)]
        arr = [[]for i in range(9)]
        chunk 
= [[]for i in range(9)] def valid_num(num, row, col): num_flag = num not in line[row] and num not in arr[col] and num not in chunk[row//3*3+col//3] return num_flag def remove(num, row, col): i = line[row].index(num) j = arr[col].index(num) k
= chunk[row//3*3+col//3].index(num) del line[row][i] del arr[col][j] del chunk[row//3*3+col//3][k] board[row][col] = '.' def add(num, row, col): line[row].append(num) arr[col].append(num) chunk[row//3*3+col//3].append(num) board[row][col] = num def check(row, col): if row == 8 and col == 8: nonlocal flag flag = True else: if col == 8: backtrace(row + 1, 0) else: backtrace(row, col + 1) def backtrace(row, col): if board[row][col] == '.': for m in range(1,10): d= str(m) if valid_num(d, row, col) is True: add(d, row, col) check(row, col) if not flag: remove(d, row, col) else: check(row, col) vex = len(board) for i in range(vex): for j in range(vex): get = board[i][j] k = i//3*3+j//3 if get is not '.': line[i].append(get) arr[j].append(get) chunk[k].append(get) # flag = False backtrace(0, 0)

值得注意的是,在check函式中,需要申明nonlocal flag在函式或其他作用域中使用外層(非全域性)變數,因為其對flag值進行了修改,否則無法使用。此處不能使用global。