按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。
n
皇后问题 研究的是如何将n
个皇后放置在n×n
的棋盘上,并且使皇后彼此之间不能相互攻击。给你一个整数
n
,返回所有不同的n
皇后问题 的解决方案。每一种解法包含一个不同的
n
皇后问题 的棋子放置方案,该方案中Q
和.
分别代表了皇后和空位。
解法 回溯
思路
彼此不能攻击代表的是任意两个皇后都不能处在同一行、同一列,或同一条斜线上。同一行和列好理解,但是怎么算对角线呢?可以用 row
和 col
所表示吗?可以的!
左上到右下满足 (row - col)
相同的点在同一条主对角线上。右上到左下满足 (row + col)
相同的点在同一条副对角线上。我们可以使用 Set
来保存现在已有的皇后的位置。
接下来就可以开始写递归函数了,如果递归到第 n
层说明已经得到答案,可以退出循环了。
然后开始构造这一层,如果三个集合中已存在皇后,那么就不在这地方放皇后。
如果找到放皇后的地方,接下来就是使用回溯框架即可,先放然后再撤销。
代码
function solveNQueens(n: number): string[][] {
const result = [];
const board = [];
const cols = new Set();
const diag1 = new Set();
const diag2 = new Set();
const dfs = (row) => {
if (row === n) {
result.push(buildBoard(board));
return;
}
for (let col = 0; col < n; col++) {
if (cols.has(col) || diag1.has(row - col) || diag2.has(row + col)) {
continue;
}
board[row] = col;
cols.add(col);
diag1.add(row - col);
diag2.add(row + col);
dfs(row + 1);
cols.delete(col);
diag1.delete(row - col);
diag2.delete(row + col);
}
};
const buildBoard = (board) => {
const res = [];
for (let i = 0; i < n; i++) {
let row = '.'.repeat(board[i]) + 'Q' + '.'.repeat(n - board[i] - 1);
res.push(row);
}
return res;
};
dfs(0);
return result;
};
时空复杂度
时间复杂度:O(n!)
空间复杂度:除开答案所需的额外空间为 O(n)