Description
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 integer n, return all distinct solutions to the n-queens puzzle.
Each solution contains a distinct board configuration of the n-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.
位操作解题
n皇后是dfs很典型的问题了
两个皇后不能在同一行、同一列或者同一斜线上
对于位操作来说,需要
n
,
k
,
l
,
r
,
x
n, k, l, r, x
n,k,l,r,x 5个参数
其中
i
n
d
e
x
index
index 是当前填充的列
n
=
2
n
−
1
n = 2^n - 1
n=2n−1 是循环结束条件,如
4
×
4
4\times 4
4×4的棋盘,
n
=
0000
0000
0000
1111
n = 0000\ 0000\ 0000\ 1111
n=0000 0000 0000 1111
k
k
k指的是哪些列已经被使用过了,由于是一行一行填的,所以行信息不用管,已经使用过的列置为1,未使用过的列置为0,更新规则为
k
=
k
∣
i
n
d
e
x
k = k | index
k=k∣index
l
,
r
l, r
l,r指的是由于不能处于斜对角导致的无法填充的位置,
l
l
l是左斜对角,
r
r
r是右斜对角,更新的时候用
(
l
∣
i
n
d
e
x
)
<
<
1
(
r
∣
i
n
d
e
x
)
>
>
1
(l | index) << 1\\ (r | index) >> 1
(l∣index)<<1(r∣index)>>1
x
x
x是当前行可以填的列,通过
n
&
(
n \& (
n&(~
(
k
∣
l
∣
r
)
)
(k | l | r))
(k∣l∣r)) 得到,如
n
=
0000
0000
1111
1111
k
=
0000
0000
1011
0000
l
=
0000
0000
1000
1000
r
=
0000
0000
0100
0100
n = 0000\ 0000\ 1111\ 1111\\ k = 0000\ 0000\ 1011\ 0000\\ l = 0000\ 0000\ 1000\ 1000\\ r = 0000\ 0000\ 0100\ 0100
n=0000 0000 1111 1111k=0000 0000 1011 0000l=0000 0000 1000 1000r=0000 0000 0100 0100
则
x
=
0000
0000
0000
0011
x = 0000\ 0000\ 0000\ 0011
x=0000 0000 0000 0011
对
x
x
x取补码再与原来的
x
x
x互与,就可以得到
x
x
x中最后一个
1
1
1的位置
对于刚刚的
x
x
x进行如上操作即有
i
n
d
e
x
=
0000
0000
0000
0001
index = 0000\ 0000\ 0000\ 0001
index=0000 0000 0000 0001
因为要记录位置,所以真正存的位置是 log 2 ( i n d e x ) \log_2(index) log2(index)
其他就和普通dfs一样,代码如下:
class Solution {
int nn;
List<List<Integer>> answer;
List<Integer> temp;
public void FindQueens(int k, int l, int r){
if(k == nn){
answer.add(new ArrayList<>(temp));
return;
}
int x = nn & (~ (k | l | r));
while(x != 0){
int index = x & (~ x + 1); //求补码,然后补码和原码求与,找到最右一个1,
x -= index;
temp.add((int)(Math.log(index)/Math.log(2)));
FindQueens(k | index, (l | index) << 1, (r | index) >> 1);
temp.remove(temp.size() - 1);
}
}
public List<List<String>> solveNQueens(int n) {
answer = new ArrayList<>();
temp = new ArrayList<>();
int k, l, r, x, i;
nn = (int) (Math.pow(2, n) - 1);
k = 0;
l = 0;
r = 0;
FindQueens(k, l, r);
List<List<String>> output = new ArrayList<>();
for(i = 0; i < answer.size(); i++){
List<Integer> curr = answer.get(i);
List<String> currs = new ArrayList<>();
String currans = "";
for(int p = 0; p < n; p++){
currans = "";
for(int q = 0; q < n; q++){
currans += q == curr.get(p)? "Q": ".";
}
currs.add(currans);
}
output.add(currs);
}
return output;
}
}
1ms解题
网上粘下来的做个记录……还没看懂快在哪里……
class Solution {
private List<List<String>> solutions;
private char[][] nQueens;
private boolean[] colUsed;
private boolean[] diagonals45Used;
private boolean[] diagonals135Used;
private int n;
public List<List<String>> solveNQueens(int n) {
solutions = new ArrayList<>();
nQueens = new char[n][n];
for (int i = 0; i < n; i++) {
Arrays.fill(nQueens[i], '.');
}
colUsed = new boolean[n];
diagonals45Used = new boolean[2 * n - 1];
diagonals135Used = new boolean[2 * n - 1];
this.n = n;
backtracking(0);
return solutions;
}
private void backtracking(int row) {
if (row == n) {
List<String> list = new ArrayList<>();
for (char[] chars : nQueens) {
list.add(new String(chars));
}
solutions.add(list);
return;
}
for (int col = 0; col < n; col++) {
int diagonals45Idx = row + col;
int diagonals135Idx = n - 1 - (row - col);
if (colUsed[col] || diagonals45Used[diagonals45Idx] || diagonals135Used[diagonals135Idx]) {
continue;
}
nQueens[row][col] = 'Q';
colUsed[col] = diagonals45Used[diagonals45Idx] = diagonals135Used[diagonals135Idx] = true;
backtracking(row + 1);
colUsed[col] = diagonals45Used[diagonals45Idx] = diagonals135Used[diagonals135Idx] = false;
nQueens[row][col] = '.';
}
}
}