题意理解:
N皇后问题指的是在一个n×n的棋盘上,防止皇后棋子,每行、每列、每45°斜角只能有一个皇后存在。
这是一道困难的题:困难在于:
如何处理棋盘,如何表示棋子。
将期盼看作是2维数组,一行一行来防止合适的棋子,似乎就好理解一些了。
‘.’表示棋子,‘Q’表示皇后
图摘自《代码随想录》
解题思路:
将其棋盘看作一个二维数组,‘.’表示棋子,‘Q’表示皇后。我们使用回溯算法来查找结果集。将其抽象为一棵树结构。
树深=棋盘行数 树宽=棋盘列数
用树深遍历行,树宽遍历Q可以取得位置——>目标是找到所有符合的结果。
图摘自《代码随想录》
1.暴力回溯+剪枝优化
前提条件,判断当前位置是否合法的,即是否能合法的放置一个皇后。
回溯的三个关键步骤:
确定返回值和参数列表
确定终止条件 :只有符合条件的放置才能放到最后一行,所以,当n=rowIndex时,终止。
确定单层递归逻辑
List<List<String>> result=new ArrayList<>();char[][] chessboard=null;public List<List<String>> solveNQueens(int n) {chessboard=new char[n][n];for(char[] row:chessboard) Arrays.fill(row,'.');backtracking(n,0);return result;}public void backtracking(int n,int rowIndex){//终止条件if(rowIndex==n){//收集结果并返回result.add(char2List(chessboard));return;}//当前行//单层逻辑for(int j=0;j<n;j++){//该位置是否能合法放置皇后,不合法则剪枝if(isValid(chessboard,rowIndex,j)) {//合法放皇后chessboard[rowIndex][j]='Q';backtracking(n,rowIndex+1);chessboard[rowIndex][j]='.';}}}//判断位置是否合法public boolean isValid(char[][] chessboard,int i,int j){//放置到第i层时,i+1层还没放int leftIndex=j;//左->右斜角检查int rightInndex=j;//右->左斜角检查while(i>0){i--;leftIndex--;rightInndex++;//列检查if(i>=0&&chessboard[i][j]=='Q') return false;//左->右斜角检查if(leftIndex>=0&&chessboard[i][leftIndex]=='Q') return false;//右->左斜角检查if(rightInndex<chessboard.length&&chessboard[i][rightInndex]=='Q') return false;}return true;}public List<String> char2List(char[][] chessboard){List<String> result=new ArrayList<>();for(char[] row:chessboard)result.add(new String(row));return result;}
2.分析
时间复杂度:O(n!) n表示皇后的个数
空间复杂度:O(n)