题意:n-皇后问题,即将n个皇后放到n*n的棋盘上满足任意两个皇后都不能攻击彼此,皇后一步能攻击其他同行、同列或者同对角线的皇后
要求:输入维度整数n,返回n皇后问题的所有不同的方案,每种方案是不同的放置布局,其中‘Q’和‘.’分别表示皇后和 空白空间。
思路:1、从结果来看,每列只有一个皇后,每行只有一个皇后。选择从行考虑(或者从列考虑,由对称性知,会得到相同的结果),使用的数据结构stack。
2、如何判断后面的位置能否放置皇后?1 每次放置一个皇后,根据其位置将后面不能放置的位置放到哈希表(排除的位置表)中。
3、如何判断不能放置的位置,即同行、同列、同对角线?采用ax+by+c=0。具体的,x=x0,y=y0,y=+-x + c0
public class Solution {
public List> solveNQueens(int n) {
List> solToString = new LinkedList<>();
List> sols = new LinkedList<>();
ArrayList path = new ArrayList<>(n);
nQueensComplete(sols, path, n, 0);
// addNQueens(sols, path, n, 0);
solsToStr(sols, solToString, n);
return solToString;
}
private void nQueensComplete(List> sols, ArrayList path, int n, int i) {
addNQueens(sols, path, n, 0);
mirrored(sols, n);
}
private void mirrored(List> sols, int n){
LinkedList> mirrorSols = new LinkedList<>();
for(List sol : sols){
ArrayList mirror = new ArrayList<>(n);
Coordinate queen = sol.get(0); //首行的元素
if(n % 2 == 1 && queen.y == (n-1)/2){ //正中间的处理,避免重复
continue;
}
mirror.add(new Coordinate(queen.x, (n-1)-queen.y));
for(int i = 1; i < sol.size(); i++){
queen = sol.get(i);
Coordinate mirQueen = new Coordinate(queen.x, (n-1)-queen.y);
mirror.add(mirQueen);
}
mirrorSols.addFirst(mirror);
}
sols.addAll(mirrorSols);
}
private void solsToStr(List> sols, List> solToString, int n) {
for(List sol : sols){
ArrayList nQueenToStr = new ArrayList<>(n);
for(Coordinate queen : sol){//按行存
String s = "";
for(int col = 0; col < n; col++){
if(col != queen.y){
s += ".";
}else{
s += "Q";
}
}
nQueenToStr.add(s);
}
solToString.add(nQueenToStr);
}
}
private void addNQueens(List> sols, ArrayList path, int n, int startRow) {
for(int col = 0; col < n; col++){
if(startRow == 0 && col >= (n+1)/2)//根据对称性将搜索减半
return;
Coordinate startPoint = new Coordinate(startRow, col);
for(int i = path.size()-1; i >= startRow; i--){
path.remove(i);
}
if(!testPoint(path, startPoint))
continue;
path.add(startPoint);
if(startRow == (n-1)){
sols.add(new ArrayList<>(path));
return;
}
addNQueens(sols, path, n, startRow+1);
}
}
private boolean testPoint(ArrayList path, Coordinate startPoint) {
for(Coordinate queen : path){
if(queen.x == startPoint.x || queen.y == startPoint.y){
return false;
}
if(startPoint.y - queen.y == startPoint.x - queen.x) //k=1
return false;
if(startPoint.y - queen.y == queen.x - startPoint.x)
return false;
}
return true;
}
public static class Coordinate{
int x;
int y;
public Coordinate(int x, int y) {
super();
this.x = x;
this.y = y;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + x;
result = prime * result + y;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Coordinate other = (Coordinate) obj;
if (x != other.x)
return false;
if (y != other.y)
return false;
return true;
}
}
}