n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。
上图为 8 皇后问题的一种解法。
给定一个整数 n,返回 n 皇后不同的解决方案的数量。
示例:
输入: 4
输出: 2
解释: 4 皇后问题存在如下两个不同的解法。
[
[".Q..", // 解法 1
"...Q",
"Q...",
"..Q."],
["..Q.", // 解法 2
"Q...",
"...Q",
".Q.."]
]
提示:
- 皇后,是国际象棋中的棋子,意味着国王的妻子。皇后只做一件事,那就是“吃子”。当她遇见可以吃的棋子时,就迅速冲上去吃掉棋子。当然,她横、竖、斜都可走一或 N-1 步,可进可退。(引用自 百度百科 - 皇后 )
解答:
与51. N皇后 2类似,只是简化了返回的要求,只需要输出可行解的总数即可。同样是回溯递归,分别使用col, diag, rever_diag
记录列,对角线,反对角线是否已经存在棋子:
class Solution {
public:
vector<int> col;
vector<int> diag;
vector<int> reverse_diag;
int totalNQueens(int n) {
col = vector<int>(n, 0);
diag = vector<int>(2*n, 0);
reverse_diag = vector<int>(2*n, 0);
return helper(n, 0);
}
int helper(int n, int row){
if(row == n){
return 1;
}
int result = 0;
for(int i = 0; i < n; i++){
if(!col[i] && !diag[i+row] && !reverse_diag[i-row+n]){
col[i] = diag[i+row] = reverse_diag[i-row+n] = 1;
result += helper(n, row+1);
col[i] = diag[i+row] = reverse_diag[i-row+n] = 0;
}
}
return result;
}
};
参考官方题解,还可以使用位运算进一步降低空间复杂度:
class Solution {
public:
int totalNQueens(int n) {
return solve(n, 0, 0, 0, 0);
}
int solve(int n, int row, int columns, int diagonals1, int diagonals2) {
if (row == n) {
return 1;
} else {
int count = 0;
int availablePositions = ((1 << n) - 1) & (~(columns | diagonals1 | diagonals2));
while (availablePositions != 0) {
// 获取最后一位为1的位置(将最后一位1以外的所有位置0)
int position = availablePositions & (-availablePositions);
// 将最后一位1置0
availablePositions = availablePositions & (availablePositions - 1);
count += solve(n, row + 1, columns | position, (diagonals1 | position) << 1, (diagonals2 | position) >> 1);
}
return count;
}
}
};
作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/n-queens-ii/solution/nhuang-hou-ii-by-leetcode-solution/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。