LeetCodehot 力扣热题100 N 皇后

class Solution {
public:
    vector<vector<string>> ans; // 存储最终结果
    
    vector<vector<string>> solveNQueens(int n) {
        vector<int> queens(n, 0);  // 记录每行皇后放置的列索引
        vector<int> col(n, 0);     // 记录列是否被占用
        vector<int> diag1(2 * n - 1, 0); // 记录主对角线是否被占用
        vector<int> diag2(2 * n - 1, 0); // 记录副对角线是否被占用
        solveQueens(queens, col, diag1, diag2, 0, n); // 递归回溯求解
        return ans;
    }

    void solveQueens(vector<int> &queens, vector<int> &col, vector<int> &diag1, vector<int> &diag2, int r, int n) {
        if (r == n) { // 所有行都成功放置皇后
            vector<string> res(n, string(n, '.')); // 生成 n*n 棋盘
            for (int i = 0; i < n; i++) {
                res[i][queens[i]] = 'Q'; // 放置皇后
            }
            ans.push_back(res); // 存入答案
            return;
        }

        for (int c = 0; c < n; c++) {
            if (col[c] == 1 || diag1[r + c] == 1 || diag2[r - c + n - 1] == 1) continue; // 剪枝

            // 放置皇后并标记
            queens[r] = c;
            col[c] = 1;
            diag1[r + c] = 1;
            diag2[r - c + n - 1] = 1;

            solveQueens(queens, col, diag1, diag2, r + 1, n); // 递归进入下一行

            // 回溯,撤销选择
            col[c] = 0;
            diag1[r + c] = 0;
            diag2[r - c + n - 1] = 0;
        }
    }
};

同一列不能有两个皇后

同一行不能有两个皇后(递归中,每次放置一个皇后在新的一行,因此不需要额外检查)

同一主对角线不能有两个皇后(r + c 唯一)

同一副对角线不能有两个皇后(r - c 唯一)

我们采用 回溯(Backtracking)+ 状态数组 来求解:

1. 用递归函数 solveQueens(r) 逐行放置皇后:

• 若 r == n,说明所有行都放置了皇后,将解法加入 ans。

• 遍历 c = 0 到 n-1 作为列,尝试在 (r, c) 放置皇后:

若当前位置可行(不与之前的皇后冲突),则标记 col[c], diag1[r + c], diag2[r - c + n - 1],然后递归求解 r + 1 行。

回溯:撤销本次选择,尝试下一个可能位置。

好的,我们一步步详细讲解 N 皇后 问题的执行流程,并展示 每次递归调用的变化,确保你完全理解它的运行方式。

🌟 问题分析

我们要在 N×N 的棋盘上放置 N 个皇后,并保证它们 不在同一行、同一列、同一主对角线或同一副对角线

🌟 执行步骤解析(以 N=4 为例)

🚀 1. 初始状态

我们从 r=0 开始,尝试在第一行 r=0 放置皇后。

棋盘:

. . . .   ← (r=0, 还未放置)

. . . .

. . . .

. . . .

🚀 2. 递归步骤

👉 尝试在 r=0 放置皇后

我们尝试在 (0,0) 放置皇后:

Q . . .   ← 放置皇后 (0,0)

. . . .

. . . .

. . . .

• 更新 col[0] = 1 (列 0 被占用)

• 更新 diag1[0+0] = 1 (主对角线 r+c=0 被占用)

• 更新 diag2[0-0+3] = 1 (副对角线 r-c+n-1=3 被占用)

👉 递归到 r=1

我们在 r=1 试图放置皇后。

• c=0 不能放(因为 col[0] = 1,列冲突)

• c=1 不能放(因为 diag1[1+1] = 1,主对角线冲突)

• c=2 可以放(无冲突)

Q . . .   ← (0,0)

. . Q .   ← 放置 (1,2)

. . . .

. . . .

更新:

• col[2] = 1

• diag1[1+2] = 1

• diag2[1-2+3] = 1

👉 递归到 r=2

在 r=2 试图放置皇后:

• c=0 可以放(无冲突)

Q . . .   ← (0,0)

. . Q .   ← (1,2)

. Q . .   ← 放置 (2,1)

. . . .

更新:

• col[1] = 1

• diag1[2+1] = 1

• diag2[2-1+3] = 1

👉 递归到 r=3

在 r=3 试图放置皇后:

• c=0 不能放

• c=1 不能放

• c=2 不能放

• c=3 可以放

Q . . .   ← (0,0)

. . Q .   ← (1,2)

. Q . .   ← (2,1)

. . . Q   ← 放置 (3,3)

找到一个解!存储到 ans

🚀 3. 回溯

我们回溯:

• 撤销 (3,3) → 继续尝试 r=3(无其他选项,回溯 r=2)

• 撤销 (2,1) → 继续尝试 r=2

• 撤销 (1,2) → 继续尝试 r=1

继续寻找新解……

最终得到 两个解

1. Q . . .      2. . Q . .

   . . Q .         . . . Q

   . . . Q         Q . . .

   . Q . .         . . Q .

🌟 复杂度分析

时间复杂度:O(N!),回溯会尝试所有可能的皇后排列,但因为剪枝,效率比 N! 好很多。

• **空间复杂度:O(N)**,只用 col, diag1, diag2` 记录状态。

🌟 总结

1. 递归逐行放置皇后

2. 检查列、主对角线、副对角线是否冲突

3. 放置皇后并递归到下一行

4. 所有行完成时,存储解法

5. 回溯撤销选择,继续尝试其他列

6. 最终输出所有解

这样,你能清楚地理解 N 皇后问题的求解过程了吗? 😃

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值