菜鸡每日一题系列打卡51天
每天一道算法题目
小伙伴们一起留言打卡
坚持就是胜利,我们一起努力!
题目描述(引自LeetCode)
n皇后问题研究的是如何将n个皇后放置在n × n的棋盘上,并且使皇后彼此之间不能相互攻击。
上图为8皇后问题的一种解法。给定一个整数n,返回所有不同的n皇后问题的解决方案。每一种解法包含一个明确的n皇后问题的棋子放置方案,该方案中'Q'和'.'分别代表了皇后和空位。
示例:
输入: 4
输出: [
[".Q..", // 解法 1
"...Q",
"Q...",
"..Q."],
["..Q.", // 解法 2
"Q...",
"...Q",
".Q.."]
]
解释: 4 皇后问题存在两个不同的解法。
提示:
皇后,是国际象棋中的棋子,意味着国王的妻子。皇后只做一件事,那就是“吃子”。当她遇见可以吃的棋子时,就迅速冲上去吃掉棋子。当然,她横、竖、斜都可走一到七步,可进可退。(引用自百度百科 - 皇后)
题目分析
N皇后问题又是一个经典的回溯法的应用场景。对于回溯法的题目已经讲的够多的了。三步走,首先创建记录回溯状态的数据结构,然后进行试探,如果试探符合要求就继续向下试探,否则就撤销本次试探。为了方便小伙伴们阅读,菜鸡对代码的结构进行了简单的拆分和注释。话不多说,上代码!
代码实现
class Solution {
// 结果集
private List<List<String>> result = new ArrayList<>();
// 记录列
private int[] rows;
// 记录主对角线
private int[] rup;
// 记录副对角线
private int[] lup;
// 记录皇后位置
private int[] queens;
public List<List<String>> solveNQueens(int n) {
rows = new int[n];
rup = new int[2 * n - 1];
lup = new int[2 * n - 1];
queens = new int[n];
backtrack(n, 0);
return result;
}
private void backtrack(int n, int row) {
// 递归终止条件
if (row >= n) return;
for (int column = 0; column < n; column++) {
// 符合N皇后的要求
if (rows[column] + rup[row - column + n - 1] + lup[row + column] == 0) {
// 试探
queens[row] = column;
rows[column] = 1;
rup[row - column + n - 1] = 1;
lup[row + column] = 1;
// 加入结果集
if (row == n - 1) {
List<String> tmp = new ArrayList<String>();
for (int i = 0; i < n; i++) {
StringBuilder builder = new StringBuilder();
for(int j = 0; j < queens[i]; j++) builder.append(".");
builder.append("Q");
for(int j = 0; j < n - queens[i] - 1; j++) builder.append(".");
tmp.add(builder.toString());
}
result.add(tmp);
}
// 回溯
backtrack(n, row + 1);
// 撤销
queens[row] = column;
rows[column] = 0;
rup[row - column + n - 1] = 0;
lup[row + column] = 0;
}
}
}
}
代码分析
对代码进行分析,时间复杂度为O(n!),而就空间而言,采用了额外的数组记录当前的回溯状态,空间复杂度为O(n)。
执行结果
学习 | 工作 | 分享
????长按关注“有理想的菜鸡”
只有你想不到,没有你学不到