N皇后¶
大名鼎鼎的难题
按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。
n 皇后问题 研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。
给你一个整数 n ,返回所有不同的 n 皇后问题 的解决方案。
每一种解法包含一个不同的 n 皇后问题 的棋子放置方案,该方案中 'Q' 和 '.' 分别代表了皇后和空位。
例如4皇后:
- 输入:
n = 4
- 输出:
[[".Q..","...Q","Q...","..Q."],["..Q.","Q...","...Q",".Q.."]]
- 解释:如上图所示,4 皇后问题存在两个不同的解法。
回溯算法¶
其实回溯就是略加优化的暴力搜索,会在不符合条件的情况下进行剪枝。
代码¶
用三个集合来记录已经放置了皇后的列、主对角线、副对角线,然后对每一行回溯搜索:
class Solution:
def solveNQueens(self, n: int) -> List[List[str]]:
def gen_board(queens):
"""格式化输出"""
board = ["." * n] * n
for i, q in enumerate(queens):
board[i] = board[i][:q] + "Q" + board[i][q + 1 :]
return board
def backtrack(row):
"""回溯搜索"""
nonlocal columns, diag1, diag2, queens, sol # 外部变量
# 递归出口
if row == n:
board = gen_board(queens)
sol.append(board)
else:
for i in range(n):
# 不满足条件的情况下就跳过这个位置
if i in columns or row - i in diag1 or row + i in diag2:
continue
# 记录答案
queens[row] = i
# 记录已经被占据的地方
columns.add(i)
diag1.add(row - i)
diag2.add(row + i)
# 压栈
backtrack(row + 1)
# 出栈
columns.remove(i)
diag1.remove(row - i)
diag2.remove(row + i)
columns = set()
diag1 = set()
diag2 = set()
sol = []
queens = [-1] * n
backtrack(0)
return sol
时间复杂度:$\mathcal{O}(N!)$,其中 N 是皇后数量。
空间复杂度:$\mathcal{O}(N)$,其中 N 是皇后数量。空间复杂度主要取决于递归调用层数、记录每行放置的皇后的列下标的数组以及三个集合,递归调用层数不会超过 N,数组的长度为 N,每个集合的元素个数都不会超过 N。
图解¶
通过可视化运行,可以清楚看到递归堆栈的过程:
最后更新: 2025-04-07 14:46:13
创建日期: 2024-12-27 23:17:42
创建日期: 2024-12-27 23:17:42