leetcode 解數獨 回溯法

2021-10-05 16:17:36 字數 3008 閱讀 5684

如:

方法:回溯法:

回溯法的思想就是:對於乙個問題有多個選擇方式,先選擇乙個方式執行下去,若在執行過程中,發現不符合規則,則回退,回到選擇方式的步驟,進而選擇其他方式,繼續試。

重要:對於回溯法,一定會有個[規則],這個[規則]將會決定是否回退,所以當我們在使用回溯法時,一定要留意能否構建[規則]

如這一題,在數獨中,規則就是:

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)

執行效果:

回溯法解數獨

前天在我的小pad上裝了個數獨遊戲,完了幾把後興趣索然了。不過突然想起來一直想寫個解數獨的程式,不過因為懶和拖拉,就一直沒寫。今天花了30分鐘寫了個解數獨的程式,貼 include include include 某個數字填入後,需要檢查的index void get affected index ...

回溯法 N皇后與解數獨

但中間也在用零碎的時間學學別的,今天寫總結一下回溯法。在最壞的情況下,回溯法會導致一次複雜度為指數時間的計算。回溯法實際上是一種 dfs 深度優先搜尋演算法 的一種,不同的是,回溯法具備剪枝的能力,下面通過兩個例子來具體分析回溯演算法。n 皇后問題是基於八皇后問題的進一步發展,如何能夠在 n n 大...

回溯演算法 解數獨

假設 判斷 假設 class solution def solve self,arr self.helper arr,0 defhelper self,arr,index if index 81 print arr return else if arr index 0 0代表需要填充資料 for i...