欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 汽车 > 新车 > LeetCode100之N皇后(51)--Java

LeetCode100之N皇后(51)--Java

2025/5/22 20:12:48 来源:https://blog.csdn.net/2301_79318558/article/details/145113541  浏览:    关键词:LeetCode100之N皇后(51)--Java

1.问题描述

        按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。

        n 皇后问题 研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。

        给你一个整数 n ,返回所有不同的 n 皇后问题 的解决方案。

        每一种解法包含一个不同的 n 皇后问题 的棋子放置方案,该方案中 'Q' 和 '.' 分别代表了皇后和空位

        示例1

输入:n = 4
输出:[[".Q..","...Q","Q...","..Q."],["..Q.","Q...","...Q",".Q.."]]
解释:如上图所示,4 皇后问题存在两个不同的解法

        示例2 

输入:n = 1
输出:[["Q"]]

        提示

  • 1 <= n <= 9

        难度等级

        困难

        题目链接

        N皇后

2.解题思路

        这道题是非常经典的N皇后问题,我们根据题目要求一步一步分析就能解决出来。

        首先,我们需要一个n*n的棋盘,并将整个棋盘用 "." 初始化,还需要一个用来存储所有方案的List集合。

        //设置棋盘char[][] chessboard = new char[n][n];//初始化棋盘for(int i = 0;i < n;i++){for(int j = 0;j < n;j++){chessboard[i][j] = '.';}}//存储最终的答案List<List<String>> data = new ArrayList<>();

        接着,其实就是一行一行的放,从0行到n-1行,在每一个位置放置皇后之后,检查能否放在这个位置而已,所以我们需要一个检查是否可以放在某个位置的方法。

        这个检查的方法也很简单,根据题目给的描述,我们只需要遍历我们要检查的位置的同一行和用一列,还用左右两个斜方向上是否有皇后就好了,如果有皇后那就不能放。检查同一行和同一列没什么好说的,要注意的是检查左右两个斜方向的时候,我们只需要检查斜上方即可,因为我们是一行一行放的,下方的棋盘还没有皇后,只有上方的棋盘有皇后。

    //检查(row,col)位置能否放置皇后public boolean check(char[][] chessboard,int row,int col){//检查同一列和同一行是否有皇后for(int i = 0;i < chessboard.length;i++){//同一列已经有皇后了if(chessboard[i][col] == 'Q'){return false;}//同一行已经有皇后了if(chessboard[row][i] == 'Q'){return false;}}//检查左斜线是否有皇后for(int i = 0; i < chessboard.length;i++){//判断检查位置是否越界if(row - i < 0){break;}//检查左斜线,斜上方if(col + i < chessboard.length && chessboard[row - i][col + i] == 'Q'){return false;}//检查右斜线,斜上方if(col - i >= 0 && chessboard[row - i][col -i] == 'Q'){return false;}}return true;}

        有了检查位置是否可以摆放皇后的方法之后,我们就可以用一个递归方法来获取所有可能的方案了。

        首先,我们要来确定递归方法需要用到的参数,棋盘肯定是必不可少的,然后是我们当前方法要摆放第几行的皇后,还需要一个存储可行方案的List集合。

    public void backtrack(char[][] chessboard,int index,List<List<String>> data)

        接着,我们就可以来确地递归的结束条件,如果index = n,说明我们已经摆完了N个皇后,当前棋盘上的方案是可行的,所以我们用一个循环将棋盘的每一行取出来存入一个方案List中,再将方案List存到存储所有可能方案的List中就可以返回了。

        //递归结束条件:如果index等于n,皇后已经全部放完if(index == chessboard.length){//添加当前方案List<String> path = new ArrayList<>();for(char[] chars:chessboard){path.add(String.valueOf(chars));}data.add(path);return;}

        然后,我们就可以来确定单层的递归逻辑了。其实上面我们已经提到了,就是尝试第index行的每一个位置,检查是否可以摆放皇后。用一个for循环遍历当前行,调用我们上面已经写好的检查方法检查当前位置是否可以摆放皇后,如果可以的话,我们就把皇后摆上去,然后递归调用方法,获取在当前基础上的所有摆放方案,获取完成之后,要记得将当前位置的皇后移去,避免影响尝试其他位置的时候,检查出错。

        //遍历当前要放皇后的行(index),检查每一个位置是否能摆放皇后for(int i = 0; i < chessboard[0].length;i++){//可以摆放皇后if(check(chessboard,index,i)){//放入皇后chessboard[index][i] = 'Q';//递归获取以当前方案为基础的所有子方案backtrack(chessboard,index+1,data);//取出皇后,尝试摆放在其他位置的方案chessboard[index][i] = '.';}}

         最后,在主方法中调用这个我们写好的递归函数并将结果返回就可以了。

3.代码展示

class Solution {public List<List<String>> solveNQueens(int n) {//设置棋盘char[][] chessboard = new char[n][n];//初始化棋盘for(int i = 0;i < n;i++){for(int j = 0;j < n;j++){chessboard[i][j] = '.';}}//存储最终的答案List<List<String>> data = new ArrayList<>();//递归获取所有可能backtrack(chessboard,0,data);//返回结果return data;}//递归获取所有的放置方案public void backtrack(char[][] chessboard,int index,List<List<String>> data){//递归结束条件:如果index等于n,皇后已经全部放完if(index == chessboard.length){//添加当前方案List<String> path = new ArrayList<>();for(char[] chars:chessboard){path.add(String.valueOf(chars));}data.add(path);return;}//遍历当前要放皇后的行(index),检查每一个位置是否能摆放皇后for(int i = 0; i < chessboard[0].length;i++){//可以摆放皇后if(check(chessboard,index,i)){//放入皇后chessboard[index][i] = 'Q';//递归获取以当前方案为基础的所有子方案backtrack(chessboard,index+1,data);//取出皇后,尝试摆放在其他位置的方案chessboard[index][i] = '.';}}}//检查(row,col)位置能否放置皇后public boolean check(char[][] chessboard,int row,int col){//检查同一列和同一行是否有皇后for(int i = 0;i < chessboard.length;i++){//同一列已经有皇后了if(chessboard[i][col] == 'Q'){return false;}//同一行已经有皇后了if(chessboard[row][i] == 'Q'){return false;}}//检查左斜线是否有皇后for(int i = 0; i < chessboard.length;i++){//判断检查位置是否越界if(row - i < 0){break;}//检查左斜线,斜上方if(col + i < chessboard.length && chessboard[row - i][col + i] == 'Q'){return false;}//检查右斜线,斜上方if(col - i >= 0 && chessboard[row - i][col -i] == 'Q'){return false;}}return true;}
}

4.总结

        这道题是一道非常非常经典的题目,但其实难度并不大,只要将需要的条件用代码表示出来,就可以迎刃而解了。好了,这道题就啰嗦到这里,祝大家刷题愉快~

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词