题意: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; } } }