leetcode36&37_SudukuSolver
36題:
一.問題描述
'.'
.A partially filled sudoku which is valid.
Note:
A valid Sudoku board (partially filled) is not necessarily solvable. Only the filled cells need to be validated.
即判斷當前部分填充的數獨是否是有效的,即每一列,每一行,每一個九宮格內沒有重讀的數字。
二.程式碼編寫
主要思想就是為每一行,每一列,每一個九宮格建立一個flag列表,然後遍歷整個數獨矩陣,去填充flag列表。flag列表內的每個元素是一個整數,
每次遍歷到的非'.'數字,則對相應flag列表的int做加法,x = 10**int(board[i][j]),這樣最後得到的int的大於1的位置則代表該列/行/九宮格內有重複數字,
則該數獨矩陣不合法。程式碼如下:
import math
class Solution(object):
def is_ok(self,x):
'''
type x: int
rtype: bool
'''
for i in str(x):
if i=='0' or i=='1':
continue
else:
return False
return True
def isValidSudoku(self, board):
"""
:type board: List[List[str]]
:rtype: bool
"""
len_bo = len(board)
len_bo_sq = int(math.sqrt(len_bo))
H = [0 for i in range(len_bo)]
S = [0 for i in range(len_bo)]
Z = [[0 for i in range(len_bo_sq)] for j in range(len_bo_sq)]
for i in range(len_bo):
for j in range(len_bo):
if board[i][j] == '.':
continue
x = 10**int(board[i][j])
H[i] += x
S[j] += x
Z[i/3][j/3] += x
for i in range(len_bo):
if self.is_ok(H[i]) == False:
return False
if self.is_ok(S[i]) == False:
return False
for i in range(len_bo_sq):
for j in range(len_bo_sq):
if self.is_ok(Z[i][j]) == False:
return False
return True
對上述題目描述中的矩陣而言,其三個flag列表值如下:行:H = [0010101000,
1001100010,
1101000000,
0101001000,
0100011010,
0011000100,
0101000100,
1000110010,
1110000000]
列:略- -
九宮格:Z=[
[1101101000,1010100010,0001000000],
[0110010000,0101001100,0001001010],
[0001000000,1100010010,1110100100]
]
37.Sudoku Solver
一.問題描述:
Write a program to solve a Sudoku puzzle by filling the empty cells.
Empty cells are indicated by the character '.'
.
You may assume that there will be only one unique solution.
A sudoku puzzle...
對數獨求解,基本規則使最後填滿的數獨是valid即可,假設解是唯一的。
二.程式碼編寫:
典型的回溯思想(DFS)求解,(類似於走迷宮,走不下去了就回溯),具體思想就是對空格子由1到9填充(這裡首先要選擇當前位置的valid解),
填好了之後填下一個。
演算法編寫的思想就是從第一個位置開始找,如果該位置不為空,則對該位置進行填充,如果填充之後數獨是valid的話,再判斷之後的剩下位置是否valid(遞迴演算法)。
判斷valid我本來直接用的36的演算法,結果TLE了,上網搜了一下發現可以優化valid的演算法。也就是說只要判斷當前填充進來的數字是否在對應行、列、九宮格中已經存在,
只要存在就返回False。程式碼如下:
class Solution(object):
def isValidSudoku(self, board,row,col,s):
# 只要判斷當前加進去的[row][col]位置的數字是否valid即可,因為之前的數獨是valid的
# 也就是隻要判斷row行沒有s,col列沒有s,九宮格內沒有s即可
"""
:type board: List[List[str]]
:type row: int
:type col: int
:type s: str
:rtype: bool
"""
len_board = len(board)
for i in range(len_board):
if board[row][i] == s:
return False
if board[i][col] == s:
return False
m = 3*(row/3)
n = 3*(col/3)
for i in range(m, m+3):
for j in range(n, n+3):
if board[i][j] == s:
return False
return True
def dfs(self, board, row, col):
len_board = len(board)
if col >= len_board:
row += 1
col = 0
if row >= len_board:
return True
if board[row][col] == '.':
for i in range(1, 10):
#board[row][col] = str(i)
if self.isValidSudoku(board,row,col,str(i)) == True:
board[row][col] = str(i)
if self.dfs(board, row, col + 1) == True:
return True
board[row][col] = '.'
return False
else:
return self.dfs(board, row, col+1)
return False
def solveSudoku(self, board):
"""
:type board: List[List[str]]
:rtype: void Do not return anything, modify board in-place instead.
"""
self.dfs(board, 0, 0)