思路:
利用深度优先(回溯算法),遍历所有格子,不符合条件的就回溯
代码:
class Solution {
public List<List<String>> solveNQueens(int n) {
int[] queens=new int[n];
Arrays.fill(queens,-1);
List<List<String>> res=new ArrayList<>();
//相当于visited(用boolean或HashSet都可以)
boolean[] col=new boolean[n];
boolean[] dials1=new boolean[2*n-1];
boolean[] dials2=new boolean[2*n-1];
bfs(res,n,0,queens,col,dials1,dials2);
return res;
}
private void bfs(
List<List<String>> res,
int n,
int index,
int[] queens,
boolean[] col,
boolean[] dials1,
boolean[] dials2
){
//index代表行
if(n==index){
List<String> board=generateBoard(queens,n);
res.add(board);
}
//遍历'列'
for(int i=0;i<n;i++){
if(!col[i]&&!dials1[index+i]&&!dials2[index-i+n-1]){
queens[index]=i;
col[i]=true;
dials1[index+i]=true;
dials2[index-i+n-1]=true;
bfs(res,n,index+1,queens,col,dials1,dials2);
col[i]=false;
dials1[index+i]=false;
dials2[index-i+n-1]=false;
queens[index]=-1;
}
}
}
private List<String> generateBoard(int[] queens,int n){
//这个函数是在最后执行的
//把queens的所有行都遍历一次
List<String> board=new ArrayList<>();
for(int i=0;i<n;i++){
char[] row=new char[n];
Arrays.fill(row,'.');
//以上的2句避免了2次循环
//queens[i]表示queens中第i个皇后所处的列
row[queens[i]]='Q';
board.add(new String(row));
}
return board;
}
}
分解:
1)这题也是一道典型的深度优先dfs算法题,设置了res、path(queens)、visited
2)这里的回溯代码:
i是遍历列,index表示行,对角线的下标分别是index+i和index-i+n-1
for(int i=0;i<n;i++){
if(!col[i]&&!dials1[index+i]&&!dials2[index-i+n-1]){
queens[index]=i;
col[i]=true;
dials1[index+i]=true;
dials2[index-i+n-1]=true;
bfs(res,n,index+1,queens,col,dials1,dials2);
col[i]=false;
dials1[index+i]=false;
dials2[index-i+n-1]=false;
queens[index]=-1;
}
}
3)generateBoard函数是最后符合条件时才执行的,核心代码:
queens[i]表示queens中第i个皇后所处的列
char[] row=new char[n];
Arrays.fill(row,'.');
//以上的2句避免了2次循环
//queens[i]表示queens中第i个皇后所处的列
row[queens[i]]='Q';
board.add(new String(row));