184 lines
4.7 KiB
Java
184 lines
4.7 KiB
Java
/*
|
|
* @lc app=leetcode id=51 lang=java
|
|
*
|
|
* [51] N-Queens
|
|
*/
|
|
|
|
// @lc code=start
|
|
|
|
import java.util.ArrayList;
|
|
|
|
class Solution {
|
|
public List<List<String>> solveNQueens(int n) {
|
|
int[][] m = createMap(n);
|
|
List<List<String>> r = new ArrayList<>();
|
|
dfsNQueen(r, m, 0, n, 0);
|
|
return r;
|
|
}
|
|
|
|
private void dfsNQueen(List<List<String>> r, int[][] m, int i, int n, int p) {
|
|
if(i == n && pass(m, n, i)) {
|
|
r.add(buildRetStr(m));
|
|
return;
|
|
} else if (i>=n) {
|
|
return;
|
|
}
|
|
if(!pass(m,n, i)) {
|
|
return;
|
|
}
|
|
for(int j = p; j<n*n; j++) {
|
|
int x = j / n;
|
|
int y = j % n;
|
|
if(m[x][y] == 0) {
|
|
m[x][y] = 1;
|
|
dfsNQueen(r, m, i+1, n, j+1);
|
|
m[x][y] = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
private boolean pass(int[][] m , int n, int i) {
|
|
// todo: check logic
|
|
return checkRow(m, n, i) && checkColumn(m, n) && checkLeftSlash(m,n) && checkRightSlash(m,n);
|
|
}
|
|
|
|
private boolean checkRow(int[][] m, int n, int s) {
|
|
for(int i=0; i<n; i++) {
|
|
if(!checkWithStrategy(m, new Point(i, 0), n, pos->{
|
|
return new Point(pos.x, pos.y+1);
|
|
})) {
|
|
return false;
|
|
}
|
|
if(i < s && !checkRowNotEmpty(m, n, i)) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
private boolean checkRowNotEmpty(int[][] m, int n, int s) {
|
|
for(int i=0; i<n; i++) {
|
|
if(m[s][i] != 0) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private boolean checkColumn(int[][] m, int n) {
|
|
for(int i = 0; i<n; i++) {
|
|
if(!checkWithStrategy(m, new Point(0, i), n, pos->{
|
|
return new Point(pos.x+1, pos.y);
|
|
})) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
private boolean checkLeftSlash(int[][] m, int n) {
|
|
for(int i = 0; i<n; i++) {
|
|
if(!checkWithStrategy(m, new Point(i, 0), n, pos->{
|
|
return new Point(pos.x+1, pos.y+1);
|
|
})) {
|
|
return false;
|
|
}
|
|
if(!checkWithStrategy(m, new Point(0, i), n, pos->{
|
|
return new Point(pos.x+1, pos.y+1);
|
|
})) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
private boolean checkRightSlash(int[][] m, int n) {
|
|
for(int i = 0; i<n; i++) {
|
|
if(!checkWithStrategy(m, new Point(0, i), n, pos->{
|
|
return new Point(pos.x+1, pos.y-1);
|
|
})) {
|
|
return false;
|
|
}
|
|
if(!checkWithStrategy(m, new Point(i, n-1), n, pos->{
|
|
return new Point(pos.x+1, pos.y-1);
|
|
})) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
private boolean checkWithStrategy(int[][] m, Point pos, int n,Function<Point, Point> incrStrategy) {
|
|
int c = 0;
|
|
if(m[pos.x][pos.y] !=0) {
|
|
c++;
|
|
}
|
|
for(int i=0;i<n-1;i++) {
|
|
pos = incrStrategy.apply(pos);
|
|
if(pos.x >=n || pos.y>= n || pos.x <0 || pos.y <0) {
|
|
break;
|
|
}
|
|
if(m[pos.x][pos.y] != 0) {
|
|
c++;
|
|
if(c>1) {
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
private int[][] createMap(int n) {
|
|
int[][] r = new int[n][n];
|
|
zset(r);
|
|
return r;
|
|
}
|
|
|
|
private void zset(int[][] m) {
|
|
if(m == null) {
|
|
return;
|
|
}
|
|
for (int i = 0; i < m.length; i++) {
|
|
if(m[i]==null) {
|
|
continue;
|
|
}
|
|
for(int j = 0; j < m[i].length; j++) {
|
|
m[i][j] = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
private List<String> buildRetStr(int[][] m) {
|
|
List<String> r = new ArrayList<String>();
|
|
if(m == null) {
|
|
return r;
|
|
}
|
|
for(int i = 0; i<m.length; i++) {
|
|
int[] t = m[i];
|
|
if(t == null) {
|
|
r.add("");
|
|
continue;
|
|
}
|
|
StringBuilder sbd = new StringBuilder();
|
|
for(int j = 0; j<t.length; j++) {
|
|
sbd.append(t[j]==0?".":"Q");
|
|
}
|
|
r.add(sbd.toString());
|
|
}
|
|
return r;
|
|
}
|
|
|
|
public static class Point {
|
|
public int x;
|
|
public int y;
|
|
|
|
public Point(int x, int y) {
|
|
this.x = x;
|
|
this.y = y;
|
|
}
|
|
}
|
|
}
|
|
// @lc code=end
|
|
|