提到回溯算法那肯定离不开 n 皇后这道算法题,它实在是太经典了。
所谓n 皇后问题,指的是如何将n
个皇后放置在n×n
的棋盘上,并且使皇后彼此之间不能相互攻击。
皇后彼此不能相互攻击,也就是说:任何两个皇后都不能处于同一条横行、纵行或斜线上。
给你一个整数n
,返回所有不同的n 皇后问题的解决方案。
每一种解法包含一个不同的n 皇后问题的棋子放置方案,该方案中'Q'
和'.'
分别代表了皇后和空位。
输入:n = 4
输出:[[".Q..","...Q","Q...","..Q."],
["..Q.","Q...","...Q",".Q.."]]
解释:4 皇后问题存在两个不同的解法。
我觉得你应该能够结合视频动画和保姆级别的代码注释把这道题目弄清楚。
classSolution{
//保存所有符合要求的解
List>res=newArrayList<>();
publicList>solveNQueens(intn){
//attack用来表示皇后的攻击范围
int[][]attack=newint[n][n];
//queen用来记录皇后的位置
char[][]queen=newchar[n][n];
//初始化二维数组queen中所有的元素为'.'
for(char[]c:queen){
Arrays.fill(c,'.');
}
//初始化二维数组attack中所有的元素为0
//0代表没有皇后能攻击得到
//1代表出于任意一个皇后的攻击范围内
for(int[]c:attack){
Arrays.fill(c,0);
}
//从棋盘的第0行第0列处理n皇后的情况
backtrack(0,n,queen,attack);
//最后,返回所有符合要求的解
returnres;
}
//很显然,每一行只能放置一个皇后,所以我们每一行每一行的来放置皇后
//k表示当前处理的行
//n表示需要放置多少个皇后,同时也代表棋盘的大小为n*n
//queen用来记录皇后的位置
//attack用来表示皇后的攻击范围
privatevoidbacktrack(intk,intn,char[][]queen,int[][]attack){
//如果发现在棋盘的最后一行放置好了皇后,那么就说明找到了一组符合要求的解
if(k==n){
//由于queen为二维字符数组,所以需要转换为字符串数组
Listlist=newArrayList<>();
//遍历二维数组queen
//取出queen的每一行字符数组c
for(char[]c:queen){
//把字符数组c中的所有字符转换为字符串的形式进行拼凑
//比如['.','Q','.','.',]
//转换为'.Q..'
//把这个字符串加入到list中
list.add(String.copyValueOf(c));
}
//list即为一组符合要求的解,把它加入到结果数组中
res.add(list);
//由于遍历完了所有的行,无需再遍历下去,所以返回
return;
}
//每一行只能放置一个皇后
//并且每一列也只能放置一个皇后
//所以在k行中,从0列到n-1列,判断皇后应该放置到哪个位置
for(inti=0;i< n ; i++){
//如果发现attack[k][i]==0
//说明这个位置不在任何一个皇后的攻击范围内
//所以可以考虑放置皇后
if(attack[k][i]==0){
//如果在(k,i)位置放置了皇后,那么就需要考虑在k+1行应该怎么放置其它的皇后了
//由于有可能在(k,i)位置放置了皇后之后,在后续的其它行会无法再放置其它的皇后
//那么就需要回到(k,i)的状态,考虑能不能在(k,i+1)的位置放置
//为了能够回到(k,i)的状态,所以需要先记录此时的attack
//使用一个临时的二维数组,深度拷贝attack
//如果不使用深度拷贝,而是直接使用int[][]temp=c
//会导致attack发生改变是temp也会发生改变
//这样也就无法保存之前的状态了
int[][]temp=newint[n][n];
//通过两个for循环,把attack中的所有元素深度拷贝到temp
for(intl=0;l< n ; l++){
for(intm=0;m< n ; m++){
temp[l][m] = attack[l][m];
}
}
//queen用来记录皇后的位置
//那么(k,i)的位置queen[k][i]='Q'
queen[k][i]='Q';
//由于新放置了一个皇后,所以攻击范围又更多了
//所以需要更新attack数组
//新放置皇后的坐标为(k,i),同样的需要更新它的八个方向
checkQueenAttack(k,i,attack);
//如果在(k,i)位置放置了皇后,那么就需要考虑在k+1行应该怎么放置其它的皇后
//递归的调用backtrack在k+1行放置皇后
backtrack(k+1,n,queen,attack);
//递归结束后,拿走皇后,恢复attack的状态,考虑能不能在(k,i+1)的位置放置
attack=temp;
//恢复queen的状态,说明此时皇后不放置在(k,i)位置
queen[k][i]='.';
}
}
}
//坐标(x,y)为皇后所处的位置
//更新attack
privatevoidcheckQueenAttack(intx,inty,int[][]attack){
//对于每一个坐标(x,y)来说,都有上、下、左、右、左上、左下、右上、右下八个方向
//【左上】的坐标为(x-1,y-1)
//【上】的坐标为(x-1,y)
//【右上】的坐标为(x+1,y+1)
//【左】的坐标为(x,y+1)
//【右】的坐标为(x,y-1)
//【左下】的坐标为(x+1,y-1)
//【下】的坐标为(x+1,y)
//【右下】的坐标为(x+1,y+1)
//通过两个一维数组可以表示这八个方向
//dx表示x的方向
intdx[]={-1,-1,-1,0,0,1,1,1};
//dy表示y的方向
intdy[]={-1,0,1,-1,1,-1,0,1};
//皇后所处的坐标肯定是皇后能攻击的位置,设置为1
attack[x][y]=1;
//以坐标(x,y)为中心,去更新它八个方向的坐标
for(intj=0;j< 8;j++){
//由内向外的进行更新
for(inti=1;i< attack.length ; i++){
//新的位置的坐标行为x+i*dx[j]
intnx=x+i*dx[j];
//新的位置的坐标列为y+i*dy[j]
intny=y+i*dy[j];
//如果新位置的坐标在n*n的棋盘范围内
if(nx>=0&&nx< attack.length && ny >=0&&ny< attack.length){
//那么这些位置就是在坐标为(x,y)的皇后的攻击范围内,更新为1
attack[nx][ny]=1;
}
}
}
}
}
审核编辑 :李倩
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。
举报投诉
-
代码
+关注
关注
30文章
4719浏览量
68211 -
回溯算法
+关注
关注
0文章
10浏览量
6590
原文标题:回溯算法经典题目之 N 皇后
文章出处:【微信号:TheAlgorithm,微信公众号:算法与数据结构】欢迎添加关注!文章转载请注明出处。
发布评论请先 登录
相关推荐
时间复杂度为 O(n^2) 的排序算法
作者:京东保险 王奕龙 对于小规模数据,我们可以选用时间复杂度为 O(n2) 的排序算法。因为时间复杂度并不代表实际代码的执行时间,它省去了低阶、系数和常数,仅代表的增长趋势,所以在小规模数据情况下
RVBacktrace RISC-V极简栈回溯组件
RVBacktrace组件简介一个极简的RISC-V栈回溯组件。功能在需要的地方调用组件提供的唯一API,开始当前环境的栈回溯支持输出addr2line需要的命令,使用addr2line进行栈回溯支持结合反汇编,栈
回溯英特尔在跨越半个世纪的发展历程
我们以英特尔三位风云人物的三句名言为线索,回溯英特尔在跨越半个世纪的发展历程中,如何利用芯片技术的力量,影响信息时代,开启未来之门。
机器学习的经典算法与应用
关于数据机器学习就是喂入算法和数据,让算法从数据中寻找一种相应的关系。Iris鸢尾花数据集是一个经典数据集,在统计学习和机器学习领域都经常被用作示例。数据集内包含3类共150条记录,每类各50个数
什么是经典蓝牙模块?
什么是经典蓝牙模块? 前面我们已经就蓝牙模块的概念做了了解,随着时间的推移,产品越来越智能,需要的蓝牙模块也就越来越广泛,本篇文章我们就一起了解下什么是经典蓝牙模块。 经典蓝牙模块(BT)泛指
求助,关于STM32上开发函数调用堆栈回溯的问题求解
1、stm32f1系列
2、上了FreeRTOS
3、想开发函数调用回溯功能
在编译选项中增加了--use_frame_pointer,编程一个正常的程序(之前一直run的),测试发现,程序启动即crash,请问有没有高手之前遇到过?
发表于 05-10 07:32
十大排序算法总结
排序算法是最经典的算法知识。因为其实现代码短,应该广,在面试中经常会问到排序算法及其相关的问题。一般在面试中最常考的是快速排序和归并排序等基本的排序
什么是后量子密码学?量子计算机vs经典计算机
后量子密码学(Post-Quantum Cryptography,PQC)是在经典计算机上定义和执行算法,研究量子计算机和经典计算机都无法破解的新密码系统。后量子密码学的提出是为了抵抗量子计算机的攻击,所以又称抗量子计算密码学。
评论