n皇后问题是将n个皇后放置在n*n的棋盘上,皇后彼此之间不能相互攻击。
给定一个整数n,返回所有不同的n皇后问题的解决方案。
每个解决方案包含一个明确的n皇后放置布局,其中“Q”和“.”分别表示一个女王和一个空位置。
样例
对于4皇后问题存在两种解决的方案:
[
[".Q..", // Solution 1
"...Q",
"Q...",
"..Q."],
["..Q.", // Solution 2
"Q...",
"...Q",
".Q.."]
]
挑战
你能否不使用递归完成?
解题思路:
DFS。这里在解题过程为了方便DFS,由于每一行必有一个元素,所以可将结果简化为一个数字数组,下标代表横坐标,值代表纵坐标,如[1,3,0,2]--> [".Q..","...Q","Q...","..Q."]。
本题的难点在于判断该点是否合法,最方便的做法是建立数组:
cols[i]表示第i列被占用、dia1[i]表示第i右对角线被占用、dia2[i]表示第i左对角线被占用
而右对角线元素的特征是一共有2*n-1个,坐标和相加相等
右对角线元素的特征是一共有2*n-1个,坐标和相减相等,但数组下标都是正数,所以再都加上n-1就为非负数了。
public class Solution {
/*
* @param n: The number of queens
* @return: All distinct solutions
*/
public List<List<String>> solveNQueens(int n) {
// write your code here
List<List<String>> res = new ArrayList<>();
cols = new boolean[n];
dia1 = new boolean[2*n-1];
dia2 = new boolean[2*n-1];
dfs(res, n, new ArrayList<Integer>(), 0);
return res;
}
//cols[i]表示第i列被占用
boolean[] cols;
//dia1[i]表示第i右对角线被占用
boolean[] dia1;
//dia2[i]表示第i左对角线被占用
boolean[] dia2;
//list存入当前结果,其中下标表示横坐标,对应的值代表纵坐标
//index表示当前这一行
private void dfs(List<List<String>> res, int n, List<Integer> list, int index){
if(list.size() == n){
res.add(generateBoard(list));
return;
}
//对列进行遍历
for(int i=0; i<n; i++){
//如果当前列,左对角线和右对角线都没被占
if(!cols[i] && !dia1[index+i] && !dia2[index-i+n-1]){
cols[i] = true;
dia1[index+i] = true;
dia2[index-i+n-1] = true;
list.add(i);
dfs(res, n, list, index+1);
cols[i] = false;
dia1[index+i] = false;
dia2[index-i+n-1] = false;
list.remove(list.size()-1);
}
}
}
//将数字表示的结果转换为String类型,其中下标表示横坐标,对应的值代表纵坐标
//如[1,3,0,2]--> [".Q..","...Q","Q...","..Q."]
private List<String> generateBoard(List<Integer> list){
int row = list.size();
List<String> res = new ArrayList<>();
for(int i=0; i<row; i++){
StringBuilder sb = new StringBuilder();
for(int j=0; j<row; j++){
if(j == list.get(i))
sb.append('Q');
else
sb.append('.');
}
res.add(sb.toString());
}
return res;
}
}