原题目链接:52. N皇后 II
题目描述:
n 皇后问题 研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。
给你一个整数 n ,返回 n 皇后问题 不同的解决方案的数量。
示例 1:
输入:n = 4
输出:2
解释:如上图所示,4 皇后问题存在两个不同的解法。
示例 2:
输入:n = 1
输出:1
1 <= n <= 9
- 皇后彼此不能相互攻击,也就是说:任何两个皇后都不能处于同一条横行、纵行或斜线上。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/n-queens-ii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
做题思路:
- 八皇后问题要采用回溯和剪枝来解决,那么什么是回溯和剪枝呢?
- 什么是回溯?
2.1 假设我们用前序遍历,遍历下面的二叉树,前序遍历就是先遍历根节点,然后左子节点,接着右子节点
2.2 红色线就是前序遍历的路线,而绿色就是回溯的路线,例如7 -> 4 -> 2 -> 1,此时,我们发现1往下没得走了,因为 1 没有子节点,所以退回到 2 节点,这个过程就叫做回溯
3. 什么是剪枝?
3.1 假如有个四皇后的问题,如图所示
3.2 在摆放第一个皇后后,我们会发现出现不可摆放的位置即黑色,那这些位置我们就可以判断出来,从而不用花费时间去尝试这些位置能不能摆放皇后,这就是剪枝操作
4. 在了解完这两个知识点之后,我还得解释一下如果利用数学的斜率k判断两个点(皇后)是否在一条对角线上
4.1 在我画的图,每个小矩形就代表一个点,假设有两个点(皇后),坐标分别是Q1(x1,y1),Q2(x2,y2),由于斜率k的计算公式是,如果这个k的值等于-1或者1,就说明两个点(皇后)是同一条对角线,那么也就是说,同一对角线只有两种情况。
4.2 第一种,(x1 - x2) = -1 * (y1 - y2),第二种,(x1 - x2) = 1 * (y1 - y2),合并上面两个情况就是,(x1 - x2) = | (y1 - y2) |
5. 最后我用四皇后的流程图走一遍
废话不多说,直接上代码,为了让各位看官更能清晰理解,我的代码写得不精简,我的代码里加了大量的注释,相信各位看官可以理解,如果我有些没写清楚或者写错的,可以评论区或者私信我喔
class Solution {
//数组下标代表行号,数组元素代表列号
//例如:cols[0] = 3,就代表第0行第3列有皇后
int[] cols;
//存放摆放皇后的方法数量
int ways;
public int totalNQueens(int n) {
if(n < 1) return 0; //如果皇后个数小于1,就没有摆放的必要了
cols = new int[n]; //初始化数组
place(0); //从第0行开始摆放
return ways;
}
/**
* 摆放皇后的方法
* @param row 代表第几行
*/
void place(int row){
if(row == cols.length){
//由于是从第0行开始摆放,依次往下摆放,说明当摆放到n行的时候,前面的已经摆放好了
//所以就算是一种正确的摆放方法
ways++;
return;
}
//确定了行,那么现在就要确定哪一列
for(int col = 0; col < cols.length; col++){
if(isValid(row,col)){ //是否可以摆放皇后
cols[row] = col;
place(row + 1); //递归调用摆放皇后的方法,一旦摆好一个皇后,就立马跳到下一行摆放下一个皇后
}
}
//代码执行到这里,说明了在进行剪枝操作
}
/**
* 判断第row行第col列是否能摆放皇后
* @param row 代表第几行
* @param col 代表第几列
*/
boolean isValid(int row, int col){
//遍历所有行
for(int i = 0; i < row; i++){
//我们依次列举三种不能摆放的情况
//第一种情况,摆好皇后后,下一个皇后不能摆放在相同行,这里由于一旦摆好一个皇后,就立马跳到下一行摆放下一个皇后,所以可以不进行处理
//第二种情况,摆好皇后后,下一个皇后不能摆放在相同列
if(cols[i] == col) return false;
//第三种情况,摆好皇后后,下一个皇后不能摆放在对象线,我这里利用数学的斜率对对角线的情况进行了处理
if(row - i == Math.abs(col - cols[i])) return false; //abs方法返回绝对值
}
//代码执行到这里,说明是可以的
return true;
}
}
都看到这里了,不考虑点个赞再走嘛?