目录
一、概述
例题只能暴力搜索,配上剪枝降低计算量
二、例题
2.1 N皇后问题(Leetcode 51)
解题思路:用set来保存已有皇后攻击范围的坐标运算常数;用递归完美解决用过的皇后的攻击范围清除
class Solution(object):
def solveNQueens(self, n):
"""
:type n: int
:rtype: List[List[str]]
"""
self.result = [] # 存储所有n皇后路径的结果
self.col, self.pie, self.na = set(), set(), set() # 分别存储皇后攻击的路径
self.DFS(n, 0, []) # 开始递归
return self.generate_result(self.result) # 转换格式
def DFS(self, n, row, cur_state):
"""
n代表总共有几行
row代表当前在第几行
cur_state代表当前的n皇后路径
"""
if row>=n:
self.result.append(cur_state)
return
for col in range(n):
if col not in self.col and row-col not in self.pie and row+col not in self.na:
# 将该层的此皇后攻击的范围加入存储
self.col.add(col)
self.pie.add(row-col)
self.na.add(row+col)
# 基于该层的此皇后的攻击范围,去找下一层能放棋子的位置
self.DFS(n, row+1, cur_state+[col])
# 基于该层的此皇后的攻击范围,已经完成了后续所有层的搜素,所以现在把该层的此皇后的攻击范围删除,目的是要遍历到该层的下一个皇后位置
self.col.remove(col)
self.pie.remove(row-col)
self.na.remove(row+col)
return
def generate_result(self, result):
# 根据n皇后路径的结果集合,转换到题目要求的格式
final_result = []
for i in range(len(result)):
sub_result = []
for j in range(len(result[i])):
tmp = ['.' for _ in range(len(result[i]))]
tmp[result[i][j]] = "Q"
sub_result.append(''.join(tmp))
final_result.append(sub_result)
return final_result
2.2 数独问题(Leetcode 36、37)
2.2.1 有效数独(Leetcode 36)
判断这道数独题目有没有出错(出错就是“行”、“列”、“三宫格”内出现了重复元素)。
class Solution(object):
def isValidSudoku(self, board):
"""
:type board: List[List[str]]
:rtype: bool
"""
# 定义存储“行”、“列”、“三宫格”的单元,用于判断是否有重复元素
self.col = [set() for _ in range(9)]
self.row = [set() for _ in range(9)]
self.square = [[set() for _ in range(3)] for _ in range(3)]
# 开始遍历数独的每一个有效元素
for i in range(9):
for j in range(9):
cur = board[i][j]
if cur == '.':
continue
if cur not in self.row[i]:
self.row[i].add(cur)
else:
return False
if cur not in self.col[j]:
self.col[j].add(cur)
else:
return False
if cur not in self.square[i/3][j/3]:
self.square[i/3][j/3].add(cur)
else:
return False
return True