题目描述:
51和52题是在给出N的时候,分别求出解的个数以及打印出各个解。
可以利用位运算解决N皇后问题。
主要思路:
与深度优先搜索+回溯的方式一致,只是在进行判断是否合理等一些细节上,选择利用位运算的方式进行处理。
利用位运算记录皇后的信息,就可以将记录皇后信息的空间复杂度从 O(N) 降到 O(1)。
具体做法是,使用三个整数 columns、diagonals_1和diagonals_2
分别记录每一列以及两个方向的每条斜线上是否有皇后,每个整数有 N 个二进制位。棋盘的每一列对应每个整数的二进制表示中的一个数位,其中棋盘的最左列对应每个整数的最低二进制位,最右列对应每个整数的最高二进制位。
用 00 代表可以放置皇后的位置,11 代表不能放置皇后的位置。
三个整数的计算方法及具体的流程详见代码,一定要记住这个流程
class Solution:
def totalNQueens(self, n: int) -> int:
if n < 1:
return []
self.count = 0
self.dfs(0, 0, 0, 0, n)
return self.count
def dfs(self, row, col, pie, na, n):
if row >= n:
self.count += 1
return
bits = ~(col | pie | na) & ((1 << n)-1) # 本来是0可以为放置的位置,现在改为1,因为不然的话取非之后,前面全是1(这样做的的主要目的是只要后n位中可以放置的部分,不然的话前面全是0无法判断是否是可以放皇后的位置)
while bits > 0:
p = bits & -bits
self.dfs(row+1, col | p, (pie | p) << 1, (na | p) >> 1, n)
bits = bits & (bits - 1)
对于51题中,要把N皇后的每一个解都打印出来的问题,只需要申请一个数组,利用这个数组保存每一行放置的位置,之后按照每行放置的位置按照要求打印出来即可,代码如下:
class Solution:
def solveNQueens(self, n: int) -> List[List[str]]:
def generateBoard(): # 这里是对解按照格式进行打印的方式,很简洁可以学习一下
board = list()
for i in range(n):
row[queens[i]] = "Q"
board.append("".join(row))
row[queens[i]] = "."
return board
def solve(row: int, columns: int, diagonals1: int, diagonals2: int):
if row == n:
board = generateBoard()
solutions.append(board)
else:
availablePositions = ((1 << n) - 1) & (~(columns | diagonals1 | diagonals2))
while availablePositions:
position = availablePositions & (-availablePositions)
availablePositions = availablePositions & (availablePositions - 1)
column = bin(position - 1).count("1")
queens[row] = column # 注意这里获得二进制对应位置的代码
solve(row + 1, columns | position, (diagonals1 | position) << 1, (diagonals2 | position) >> 1)
solutions = list()
queens = [-1] * n
row = ["."] * n
solve(0, 0, 0, 0)
return solutions
复杂度分析
时间复杂度:O(N!),其中 N 是皇后数量。
空间复杂度:O(N),其中 N 是皇后数量。由于使用位运算表示,因此存储皇后信息的空间复杂度是 O(1),空间复杂度主要取决于递归调用层数,递归调用层数不会超过 N。
本文介绍了一种使用位运算解决N皇后问题的方法,通过记录每一列及斜线上的皇后位置来减少空间复杂度,实现高效求解。文章提供了具体算法流程及代码实现。
3858

被折叠的 条评论
为什么被折叠?



