数据结构与算法: 八皇后问题(详细流程)
Posted android超级兵
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构与算法: 八皇后问题(详细流程)相关的知识,希望对你有一定的参考价值。
数据结构与算法: 八皇后回溯递归问题(详细流程!!)
Tips: 采用java语言, 关注博主,底部附有完整代码
采用到的知识点:
- 递归
- 一维数组
什么是8皇后问题?
在一个8 x 8 的二维数组上, 每一个位置行 , 列 和 斜面 不允许有另一个元素存在
例如这样
定义规则
这里只需要定义一个存放每一列的一维数组即可,这样就可以保证每一行都不会有相同的元素
for(i = 0; i < 8 ; i++)
// 循环每一行
例如上面效果图对应的就是 0 , 4 , 7 ,5 , 4, 6, 1, 3
对应成二维数组就是 [0,0] , [1,4] , [2,3] , [3,5] , [4,2] , [5,6] , [6,1] , [7,3]
先来看完整代码,在逐步分析!
/*
* @author: android 超级兵
* @create: 2022-05-11 13:34
* TODO
**/
public class Client
// 女皇个数
int mQueenMax = 8;
// 存放每一列的坐标
int[] mQueens = new int[mQueenMax];
// 记录一共打印的次数
private int count = 0;
public static void main(String[] args)
Client client = new Client();
// 从第0行开始递归
client.check(0);
System.out.printf("执行完毕 一共有%d种解法", client.count);
// 用来递归赋值
public void check(int k)
if (k == mQueenMax)
// 打印当前数据
show();
return;
// 循环每一个皇后 每一行
for (int i = 0; i < mQueenMax; i++)
mQueens[k] = i;
// 判断是否满足列不相同,斜线上不相同的条件,如果满足就开始递归,进行下一行的赋值
if (isContains(k))
// 递归调用 只要满足条件就会开始递归下一行
check(k + 1);
/*
* TODO 判断之前所有行,判断是否包含某个皇后
* @param k: 每一行
*/
public boolean isContains(int k)
System.out.println("isContains = " + k);
// 循环每一行
for (int i = 0; i < k; i++)
// mQueens[i] == mQueens[n] 判断列是否相等
// Math.abs(n - i) == Math.abs(mQueens[n] - mQueens[i])
// 判断斜线上是否相等
// 如果两个点在同一条斜线上,那么他们俩 行相减 和 列相减 的值肯定相同
// 如果列上有相同的点 或者 斜线上有相同的点
if (mQueens[i] == mQueens[k] || Math.abs(k - i) == Math.abs(mQueens[k] - mQueens[i]))
return false;
System.out.println();
return true;
// 打印当前数据
public void show()
count++;
for (int item : mQueens)
System.out.printf("%d\\t", item);
System.out.println();
分析
如何做到每一列上的点各不相同
通俗的说就是一维数组中元素各不相同
/**
* @param k: 行
*/
public boolean isContains(int k)
// 循环每一行,为了判断每一列是否有相同的元素
for (int i = 0; i < k; i++)
// mQueens[i] 每一行的元素
// mQueens[k] 当前的值
// mQueens[i] == mQueens[k] 判断列是否相等
// 如果相等,那么则表示每一行有相同的元素,返回false
if (mQueens[i] == mQueens[k])
return false;
// 循环完所有的,没有列相同的元素,返回true
return true;
当前效果:
如何做到斜线上没有相同的元素
假设当前点是(4,5) , 需要判断 斜线上的点,那么则需要判断这些点
辅助图:
判断两个点是否在同一条斜线上,那么他们俩 行相减 和 列相减 的绝对值
一定相同
当前点:(4 ,5)
随机选取几个点: (6, 3) (0,1) (3,6) (2,7) (6,7)
-
4 - 6 = -2 行相减
5 - 3 = 2 列相减 -
4 - 0 = 4 行相减
5 - 1 = 4 列相减 -
4-3 = 1
5-6 = -1
-
4 -2 = 2
5-7 = -2
-
4-6 = -2
5-7 = -2
那么这段代码就应该这么写:
/**
* @param k: 行
*/
public boolean isContains(int k)
// 循环每一行
for (int i = 0; i < k; i++)
// mQueens[i] 数组中的每一个值
// mQueens[k] 当前的值
// mQueens[i] == mQueens[k] 判断列是否相等
// 如果相等,那么则表示每一列有相同的元素,返回false
if (mQueens[i] == mQueens[k]|| Math.abs(k - i) == Math.abs(mQueens[k] - mQueens[i]))
return false;
// 循环完所有的,没有列相同的元素,返回true
return true;
- Math.abs(k - i) 每一行相减的绝对值
- Math.abs(mQueens[k] - mQueens[i]) 每一列相减的绝对值
目前的效果图:
递归调用代码分析
接下来在分析一下这段代码
int mQueenMax = 8;
// 用来递归赋值
public void check(int k)
if (k == mQueenMax)
// 打印当前数据
show();
return;
// 循环每一个皇后 每一行
for (int i = 0; i < mQueenMax; i++)
mQueens[k] = i;
// 判断是否满足列不相同,斜线上不相同的条件,如果满足就开始递归,进行下一行的赋值
if (isContains(k))
// 递归调用 只要满足条件就会开始递归下一行
check(k + 1);
这里一定要把眼睛擦亮,是循环每一行里面嵌套递归!
慢慢分析,由浅入深!
先来分析循环:
既然是循环每一行,那么效果应该是这样的:
但是,在代码中, 首先通过 isContains()
方法来判断是否有列相同,或者斜线相同的元素
在0的位置一定满足条件,那么就会往下执行递归
效果图就是这样的:
然后一直走一直走,最终大致流程是这样的:
循环第8次的时候,就会发现每一个元素都不满足条件,都不满足条件的话本次递归就结束了,然后继续接着执行第7次的循环
再来看看这段代码
int mQueenMax = 8;
// 默认第一次的时候传入0
public void check(int k)
// 如果k == 8 就结束递归
if (k == mQueenMax)
show();
return;
// 循环每一个皇后 每一行
for (int i = 0; i < 8; i++)
mQueens[k] = i;
// 判断是否满足列不相同,斜线上不相同的条件,如果满足就开始递归,进行下一行的赋值
if (isContains(k))
// 递归调用 只要满足条件就会开始递归下一行
check(k + 1);
再来看一眼效果图:
最终最终就会通过:
if (k == mQueenMax)
show();
return;
public void show()
count++;
for (int item : mQueens)
System.out.printf("%d\\t", item);
System.out.println();
这段代码来打印第一次的结果0, 4, 7, 5, 2, 6, 1, 3
看到这里你以为就结束了嘛? 虽然有return
但是别忘记了,这是递归,第7次的for循环还在继续呢. 所以还需要一直走
这样的解法一共有92种
虽然只有不到60行代码,但这一段代码绝对值得深思,功底太深厚了! 可惜原创不是我 🥹
好了 本篇就结束了! 886
原创不易,您的关注与点赞就是对我最大的支持!
以上是关于数据结构与算法: 八皇后问题(详细流程)的主要内容,如果未能解决你的问题,请参考以下文章