这是我参与8月更文挑战的第19天,活动详情查看:8月更文挑战
前言
力扣第五十二题 N皇后 II
如下所示:
n 皇后问题 研究的是如何将 n
个皇后放置在 n×n
的棋盘上,并且使皇后彼此之间不能相互攻击。
给你一个整数 n
,返回 n 皇后问题 不同的解决方案的数量。
示例 1:
输入: n = 4
输出: 2
解释: 如上图所示,4 皇后问题存在两个不同的解法。
示例 2:
输入: n = 1
输出: 1
提示:
1 <= n <= 9
- 皇后彼此不能相互攻击,也就是说:任何两个皇后都不能处于同一条横行、纵行或斜线上。
一、思路
N皇后 II
和 力扣第五十一题-N 皇后
基本是一样。上一题求的是所有的解,这一题求得是解的数量。
题目中有三个非常重要的信息:
皇后
彼此不能在同一行皇后
彼此不能在同一列皇后
彼此不能在同一斜线
大致的思路分为以下几个部分:
- 使用一个二维数组存储已选择的点在行列及斜线的占用情况
- 因为每一行都会有一个
皇后
,所以当前递归中只遍历当前行的元素(剪枝)
变量说明:
boolean[][] positions; // 选择的元素
int[][] flags; // 占用情况(包含行、列、斜线)
与上一题不同的是,这一题只使用了一个 二维int数组
来存储三种占用情况。不管是 行占用
、列占用
还是 斜线占用
,只要是 占用
就将 flags[i][j] + 1
。
使用一个二维数组存储占用情况,有两个好处:
- 占用的空间变少了,由之前的三个二维数组变为了只使用一个二维数组
- 代码更简洁,在
递归
时只需要判断flags[i][j]
是否等于0
即可
其他的思路均与上一题相同,故不再过多分析。
二、实现
实现代码
实现代码与思路中保持一致
tips:因为不需要返回结果,所以在每次找到结果后只需要将
ret ++
即可
boolean[][] positions; // 选择元素记录
int[][] flags; // 占用情况(包含行、列、斜线)
int len;
int ret = 0;
public int totalNQueens(int n) {
flags = new int[n][n];
positions = new boolean[n][n];
len = n;
dfs(0);
return ret;
}
/**
* 递归
*/
public void dfs(int count) {
if (count == len) {
++ret;
return;
}
// 每一行都会有一个皇后,所以只需遍历n次
for (int i=0; i<len; i++) {
// 判断当前列是否可以放置皇后
if (flags[count][i] == 0) {
// 更新
positions[count][i] = true;
updateFlags(count, i, true);
// 向下递归
dfs(count+1);
positions[count][i] = false;
updateFlags(count, i, false);
}
}
}
public void updateFlags(int row, int col, boolean flag) {
// 更新行
for (int i=0; i< len; i++) {
flags[row][i] = flag ? flags[row][i] + 1 : flags[row][i] -1;
}
// 更新列
for (int i=0; i<len; i++) {
flags[i][col] = flag ? flags[i][col] + 1 : flags[i][col] -1;
}
// 更新斜线
int tRow = row; // 起始点(斜向下)
int tCol = col;
while (tRow>0 && tCol >0) {
tRow--;
tCol--;
}
// 更新斜向下
while (tRow<len && tCol<len) {
flags[tRow][tCol] = flag ? flags[tRow][tCol] + 1 : flags[tRow][tCol] -1;
tRow++;
tCol++;
}
tRow = row; // 起始点(斜向上)
tCol = col;
while (tRow>0 && tCol<len-1) {
tRow--;
tCol++;
}
// 更新斜向上
while (tRow<len && tCol>-1) {
flags[tRow][tCol] = flag ? flags[tRow][tCol] + 1 : flags[tRow][tCol] -1;
tRow++;
tCol--;
}
}
测试代码
测试代码如下所示:
public static void main(String[] args) {
new Number51().totalNQueens(8);
}
结果
三、总结
感谢看到最后,非常荣幸能够帮助到你~♥