n皇后问题是将n个皇后放置在n*n的棋盘上,皇后彼此之间不能相互攻击。
给定一个整数n,返回所有不同的n皇后问题的解决方案。
每个解决方案包含一个明确的n皇后放置布局,其中“Q”和“.”分别表示一个女王和一个空位置。
样例
对于4皇后问题存在两种解决的方案:
[
[".Q..", // Solution 1
"...Q",
"Q...",
"..Q."],
["..Q.", // Solution 2
"Q...",
"...Q",
".Q.."]
]
题目要求的意思就是每一行,每一列,每一斜行的皇后不能多于1个。
递归。还是和LintCode 电话号码的字母组合思想类似。
假设是4皇后问题,那么每一行可以放皇后的位置有4个(即每一列)。递归在每一行放皇后,最后一行放完之后,就是一个可能的解(还没有检查是否符合规则),用二维数组存放。然后对所有的解在检查规则,每一列,每一斜。写完代码之后,在LintCode上面超时了(感觉是枚举了所有的可能,然后又对每种检查一遍的原因)。
然后在网上参考别人的文章,可以采用一维数组来存解。a[i]表示第i行的皇后放在第a[i]列。这在检查规则时候更容易。然后不再是枚举出所有可能的解之后再检查,而是每一行放置皇后时,就检查。看代码:
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>> result=new ArrayList<List<String>>();//存放最终所有结果
List<Integer> tempResult=new ArrayList<Integer>();//存放某一个结果
recursion(result,tempResult,n);
return result;
}
public static int recursion(List<List<String>> result,List<Integer> tempResult,int n){
if(tempResult.size()==n){//如果长度等于n,就是所有皇后放完了,就存到result中。
List<String> s=new ArrayList<String>();
for(int i=0;i<n;i++){
String row="";
for(int j=0;j<n;j++){
if(tempResult.get(i)==j){
row+="Q";
}
else{
row+=".";
}
}
s.add(new String(row));
}
result.add(new ArrayList<String>(s));
return 1;
}
for(int i=0;i<n;i++){//每一行可以放在n列中的任意一列
boolean flag=true;
for (int j=0;j<tempResult.size();j++){
int absTemp1=j-tempResult.get(j);
int absTemp2=tempResult.get(j)+j;
if((absTemp1==tempResult.size()-i) || (absTemp2==tempResult.size()+i)){
flag=false;
break;
}
}
if((!tempResult.contains(i))&&flag){
tempResult.add(new Integer(i));
}
else{
continue;
}
recursion(result,tempResult,n);
tempResult.remove(tempResult.size()-1);
}
return 1;
}
}
说一下判断斜行的问题,之前用二维数组时候,就是遍历所有的斜行,统计每一斜行的皇后个数(O(n2))。用一维数组时,观察可以发现在同一斜行上的所有位置,其行-列(\)的值 或行+列(/)的值都相等,所以O(n)就可以判断。