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...
二.代码编写:
典型的回溯思想(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)