N-Queens
Hard
The n-queens puzzle is the problem of placing n
queens on an n × n chessboard such that no two queens attack each other.
Given an integern, return all distinct solutions to then-queens puzzle.
Each solution contains a distinct board configuration of then-queens' placement, where'Q'
and'.'
both indicate a queen and an empty space respectively.
Example:
Input:
4
Output:
[
[".Q..", // Solution 1
"...Q",
"Q...",
"..Q."],
["..Q.", // Solution 2
"Q...",
"...Q",
".Q.."]
]
Explanation:
There exist two distinct solutions to the 4-queens puzzle as shown above.
Solution
Backtracking
class Solution {
public List<List<String>> solveNQueens(int n) {
List<List<String>> ans = new ArrayList<>();
if (n <= 0) {
return ans;
}
searchHelper(n, new ArrayList<Integer>(), ans);
return ans;
}
// Backtracking recursively find the valid solutions
private void searchHelper(int n, List<Integer> cols, List<List<String>> ans) {
if (cols.size() == n) {
ans.add(drawBoard(cols));
return;
}
for (int col = 0; col < n; col++) {
if (!isValid(col, cols)) {
continue;
}
cols.add(col);
searchHelper(n, cols, ans);
cols.remove(cols.size() - 1);
}
}
// Output the one solution of the board in desired format
private List<String> drawBoard(List<Integer> cols) {
List<String> board = new ArrayList<String>();
for (int i = 0; i < cols.size(); i++) {
StringBuilder sb = new StringBuilder();
// draw the row
for (int j = 0; j < cols.size(); j++) {
if (cols.get(i) == j) {
sb.append("Q");
continue;
}
sb.append(".");
}
board.add(sb.toString());
}
return board;
}
// Check if the new position to be placed is invalid
private boolean isValid(int col, List<Integer> cols) {
if (cols.size() == 0) {
return true;
}
for (int row = 0; row < cols.size(); row++) {
if (col == cols.get(row)) {
return false;
}
if (cols.get(row) - row == col - cols.size()) {
return false;
}
if (cols.get(row) + row == col + cols.size()) {
return false;
}
}
return true;
}
}
更取巧的方式是,利用一个皇后会占用这个格子的所有行,列以及对角线的特点,维护所有“行,列,45度对角线,135度对角线” 的 boolean array,这样在每次考虑一个新位置的时候,只需要 的时间进行一次操作就可以了。
public class Solution {
public List<List<String>> solveNQueens(int n) {
boolean[]
//ocp0 = new boolean[n],
ocp90 = new boolean[n],
// 总共 2n - 1 种可能性,(0,0) 的 index 是 n - 1
ocp45 = new boolean[2 * n - 1],
ocp135 = new boolean[2 * n - 1];
List<List<String>> ans = new ArrayList<List<String>>();
char[][] map = new char[n][n];
for (char[] tmp : map) Arrays.fill(tmp, '.'); //init
solve(0, n, map, ans, ocp45, ocp90, ocp135);
return ans;
}
private void solve(int depth, int n, char[][] map, List<List<String>> ans,
boolean[] ocp45, boolean[] ocp90, boolean[] ocp135) {
if (depth == n) {
addSolution(ans, map);
return;
}
for (int j = 0; j < n; j++)
// 每次都进行新的一行,所以行不用检查
// 90度代表棋盘的列
// 45度对角线(从左上到右下)同一条线上 row + col 是相等的,因此可用作 index
// 135度对角线(从左下到右上)可从 (0,0) 即 index (n - 1) 为起点
// 因为同一条对角线 row - col 值恒定,可用作 offset 表示对角线的 index.
if (!ocp90[j] && !ocp45[depth + j] && !ocp135[j - depth + n - 1]) {
ocp90[j] = true;
ocp45[depth + j] = true;
ocp135[j - depth + n - 1] = true;
map[depth][j] = 'Q';
solve(depth + 1, n, map, ans, ocp45, ocp90, ocp135);
ocp90[j] = false;
ocp45[depth + j] = false;
ocp135[j - depth + n - 1] = false;
map[depth][j] = '.';
}
}
private void addSolution(List<List<String>> ans, char[][] map) {
List<String> cur = new ArrayList<String>();
for (char[] i : map) cur.add(String.valueOf(i));
ans.add(cur);
}
}
Last updated