62.N皇后

7 阅读2分钟

题目链接

按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。

n 皇后问题 研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。

给你一个整数 n ,返回所有不同的 n 皇后问题 的解决方案。

每一种解法包含一个不同的 n 皇后问题 的棋子放置方案,该方案中 Q. 分别代表了皇后和空位。

解法 回溯

思路

彼此不能攻击代表的是任意两个皇后都不能处在同一行、同一列,或同一条斜线上。同一行和列好理解,但是怎么算对角线呢?可以用 rowcol 所表示吗?可以的!

左上到右下满足 (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)