leetcode刷題-37解數獨
阿新 • • 發佈:2020-08-03
題目
編寫一個程式,通過已填充的空格來解決數獨問題。
一個數獨的解法需遵循如下規則:
數字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。