Leetcode 037 解數獨 思路詳解 python
阿新 • • 發佈:2019-02-15
編寫一個程式,通過已填充的空格來解決數獨問題。
一個數獨的解法需遵循如下規則:
- 數字
1-9
在每一行只能出現一次。 - 數字
1-9
在每一列只能出現一次。 - 數字
1-9
在每一個以粗實線分隔的3x3
宮內只能出現一次。
空白格用 '.'
表示。
一個數獨。
答案被標成紅色。
Note:
- 給定的數獨序列只包含數字
1-9
和字元'.'
。 - 你可以假設給定的數獨只有唯一解。
- 給定數獨永遠是
9x9
形式的。
思路:通過暴力搜尋,每次確定往一個位置填入資料,填完後繼續往下一個位置用遞迴的方式填,直到所有遞迴函式返回true,結果才為true。整體分為主函式,遞迴函式,判斷位置是否有效函式。整體思路與八皇后相似,通過在迴圈中遞迴的手段不斷回溯嘗試可能的值。具體表現為我們程式碼裡的for k in '123456789', 這句for迴圈搭配我們在if裡的遞迴起的效果是:我把目前這個位置填‘1’,電腦你負責幫我算我這裡填‘1’能不能解,換言之,電腦你要嘗試後面所有待填位置的所有解來告訴我這裡填‘1’ok不ok。如果不行,好,那我換‘2’,同樣,電腦你需要幫我算後面所有待填位置所有組合加上我在這個位置填的‘2’能不能構成一組解,也即我這裡填‘2’到底解不解的了。
程式碼及超詳細解釋:
class Solution(object): def isValue(self,board,x,y): #檢查填入的座標是否與行中已有元素相等 #列符合 for i in range(9): if i != x and board[i][y] == board[x][y]: return False #檢查行是否符合 for j in range(9): if j != y and board[x][j] == board[x][y]: return False #檢查每個正方形是否符合 #以下程式碼教會了我們如何遍歷3*3方塊 m = 3*(x // 3);n = 3*(y // 3) for i in range(3): for j in range(3): if (i + m != x or j + n != y) and board[i + m][j + n] == board[x][y]: return False return True def dfs(self,board): #遍歷每一個座標 for i in range(9): for j in range(9): #找board裡的需要填入的位置 if board[i][j] == '.': #從可選之間選一個 for k in '123456789': board[i][j] = k #在if的時候呼叫遞迴 #如果這個遞迴可以返回true並且當前填入的數字也沒毛病 #則證明我們解完了數獨 if self.isValue(board,i,j) and self.dfs(board): return True #到這個位置說明填入的數不太行,所以把它先空著。 board[i][j] = '.' #進行完當前可選的所有數字都不行,說明上一次決策有問題,返回false return False #所有'.'都填滿,並且沒毛病,返回true return True def solveSudoku(self, board): """ :type board: List[List[str]] :rtype: void Do not return anything, modify board in-place instead. """ self.dfs(board)