力扣51:N皇后(回溯+剪枝)java
·
解决思路:回溯 + 剪枝
N 皇后问题是经典的回溯算法应用场景,核心是在 n×n 的棋盘上放置 n 个皇后,使它们互不攻击(不在同一行、同一列、同一对角线)。下面用回溯 + 剪枝的思路来拆解这个问题。
一、问题分析
要让皇后互不攻击,需满足三个条件:
- 同一行:因为我们逐行放置皇后,所以每行只会有一个皇后,天然满足。
- 同一列:每列只能放一个皇后。
- 同一对角线:分为主对角线(行 - 列差值固定)和副对角线(行 + 列和固定),这两类对角线也只能各放一个皇后。
二、核心思路:回溯 + 剪枝
1. 回溯逻辑
- 逐行放置皇后(从第 0 行到第 n-1 行)。
- 对当前行的每一列,尝试放置皇后,若合法则递归处理下一行;若不合法则跳过(剪枝)。
- 递归完成后回溯:撤销当前列的选择,尝试下一列。
2. 剪枝策略(用三个布尔数组标记 “已占用”)
invalidColumn[]:标记某一列是否已被皇后占用。invalidMainDiagonal[]:标记某条主对角是否已被占用。invalidAntiDiagonal[]:标记某条副对角线是否已被占用。
3. 结果构造
当递归到第 n 行(即curRow == n)时,说明找到了一种合法的放置方式。此时将列索引转换为棋盘字符串(Q表示皇后,.表示空位),存入结果集。
三、步骤总结
- 初始化三个剪枝数组,分别标记列、主对角线、副对角线的占用状态。
- 从第 0 行开始,逐行尝试在每一列放置皇后:
- 若当前列或者对角线已被占用,跳过(剪枝)。
- 若合法,标记占用状态,递归处理下一行。
- 递归返回后,回溯(撤销占用标记,移除当前列选择)。
- 当找到 n 个皇后的合法放置时,构造棋盘字符串并保存结果。
这种思路通过剪枝避免了大量无效尝试,确保算法效率,是解决 N 皇后问题的经典且高效的方法。
class Solution {
public static List<List<String>> solveNQueens(int n) {
// 若invalidColumn[x] == true, 下标为x的列不能放
boolean[] invalidColumn = new boolean[n];
// 若invalidMainDiagonal[x] == true, 则(横坐标-纵坐标+n == x)的位置不能放
boolean[] invalidMainDiagonal = new boolean[2 * n + 1];
// 若invalidAntiDiagonal[x] == true, 则(横坐标 + 纵坐标 == x)的位置不能放
boolean[] invalidAntiDiagonal = new boolean[2 * n + 1];
List<List<String>> result = new ArrayList<>();
a(invalidColumn, invalidMainDiagonal, invalidAntiDiagonal, n, result, new ArrayList<>(), 0);
return result;
}
// cur存的是从第0行到第n行的棋的纵坐标
// curRow 是当前操作行数
public static void a(boolean[] invalidColumn, boolean[] invalidMainDiagonal, boolean[] invalidAntiDiagonal, int n,List<List<String>> result, List<Integer> cur, int curRow) {
if (curRow == n) {
b(result, cur);
return;
}
for (int i = 0; i < n; i++) {
if (invalidColumn[i] || invalidMainDiagonal[curRow - i + n] || invalidAntiDiagonal[curRow + i]) {
continue;
}
cur.add(i);
invalidColumn[i] = true;
invalidMainDiagonal[curRow - i + n] = true;
invalidAntiDiagonal[curRow + i] = true;
a(invalidColumn, invalidMainDiagonal, invalidAntiDiagonal, n, result, cur, ++curRow);
curRow--;
cur.remove(cur.size() - 1);
invalidColumn[i] = false;
invalidMainDiagonal[curRow - i + n] = false;
invalidAntiDiagonal[curRow + i] = false;
}
}
//插入一次结果
public static void b(List<List<String>> result, List<Integer> columnIndexs) {
List<String> temp = new ArrayList<>();
for (int index : columnIndexs) {
StringBuilder s = new StringBuilder("");
for (int i = 0; i < columnIndexs.size(); i++) {
if (i == index) {
s.append("Q");
continue;
}
s.append(".");
}
temp.add(s.toString());
}
result.add(temp);
}
}
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐



所有评论(0)