如:
方法:回溯法:
回溯法的思想就是:對於一個問題有多個選擇方式,先選擇一個方式執行下去,若在執行過程中,發現不符合規則,則回退,回到選擇方式的步驟,進而選擇其他方式,繼續試。
重要:對於回溯法,一定會有個[規則],這個[規則]將會決定是否回退,所以當我們在使用回溯法時,一定要留意能否構建[規則]。
如這一題,在數獨中,規則就是:
1. 在同一列和同一行中,不能出現一樣的數字。
2. 在同一個九宮格中,也不難出現同樣的數字。
所以我們需要用代碼構建規則:
def ok(self,board,i:int,j:int,x:str) -> bool:
for t in range(9):
if board[t][j] == x:return False #(i,j)的同一列中是否已經出現x
if board[i][t] == x:return False #(i,j)的同一行中是否已經出現x
if board[i//3* 3 + t//3][j//3*3 + t%3] == x: return False #(i,j)的同一個九宮格中是否已經出現x
return True
然後我們進入進一步的討論:
在回溯法中,我們需要構造一個[鏈式標籤](這是我的說法),意思是:噹噹前有多種方式可以選擇時,我們隨機選一種,但並不清楚這種方式是否選得正確,所以當前狀態的正確性是由接下去的步驟決定的,若在下面的步驟中,發現與現在的規則不相符,則表明上一步的選擇是False的,所以回退到上一步驟,選擇其他方式。 要想獲得True,只有一種可能,就是程序能順利執行到結束,所有的選擇都與規則相符,纔會返回True。否則中間只要有一步錯了,就會返回False,一返回False就要回退重新選擇。
那如果實現這種方式呢?答案是用遞歸。代碼如下:
代碼:
class Solution:
def solveSudoku(self, board) -> None:
self.sudoke(board,0,0)
def sudoke(self,board,i:int,j:int):
if j<=8: #若列沒有越界
if board[i][j] != ".": #當前位置若不爲空,不需要填入數字,直接去下一個位置
if i<8: #若未到最後一行,則到下一行的位置
if(self.sudoke(board,i+1,j)):return True
else: #若已經是最後一行,則到下一列的起始位置
if(self.sudoke(board,0,j+1)):return True
return False
else: #當前位置爲空,需要填入數字
for x in range(1,10): #從1-9選數字填入空格
if not self.ok(board,i,j,str(x)):continue
board[i][j] = str(x)
if i<8: #若未到最後一行,則到下一行的位置
if(self.sudoke(board,i+1,j)):return True
else: #若已經是最後一行,則到下一列的起始位置
if(self.sudoke(board,0,j+1)):return True
board[i][j] = '.' #若上訴步驟返回false,則清空當前位置填入的數字
return False #若1-9的9個數字都不符合填入規則,則返回False
return True
#判斷條件:判斷x能不能被填入
def ok(self,board,i:int,j:int,x:str) -> bool:
for t in range(9):
if board[t][j] == x:return False #(i,j)的同一列中是否已經出現x
if board[i][t] == x:return False #(i,j)的同一行中是否已經出現x
if board[i//3* 3 + t//3][j//3*3 + t%3] == x: return False #(i,j)的同一個九宮格中是否已經出現x
return True #若x符合填入條件,返回True。否則返回False
board = [['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']]
s = Solution()
s.solveSudoku(board)
for x in board:
print(x)
運行效果: