1. 题目
n 皇后问题 研究的是如何将 n
个皇后放置在 n × n
的棋盘上,并且使皇后彼此之间不能相互攻击。
给你一个整数 n
,返回 n 皇后问题 不同的解决方案的数量。
示例 1:
1 2 3
| 输入:n = 4 输出:2 解释:如上图所示,4 皇后问题存在两个不同的解法。
|
示例 2:
提示:
2. 思路
- N皇后的本质在于限制每一列 & 每一对角线(包含左对角线与右对角线)均只能够包含存在一颗棋子
- 提前需要知道的是每一个方向对角线的数量为
n * 2 - 1
条,如下所示:
- 初始化列数组
cols
与左右对角线数组leftDiagonals, rightDiagonals
,其中列数组的长度为n
,左右对角线数组的长度为n * 2 - 1
- 初始化回溯函数
helper(int row)
,回溯模板为以下:
1 2 3 4 5 6 7 8 9 10 11 12
| void backtracking(参数) { if (终止条件) { 存放结果; return; }
for (选择:本层集合中元素(树中节点孩子的数量就是集合的大小)) { 处理节点; backtracking(路径,选择列表); 回溯,撤销处理结果 } }
|
- 回溯函数中,终止条件为当
row == n
时,将全局result
变量进行+1
,同时终止回溯
- 回溯过程中,入参单位为每一行的矩阵,深度回溯的过程中,使用的是每一列
- 在判断该坐标允许放置棋子时,需要将列数组、左右对角线数组标记为占用状态
- 其中左对角线的计算为
row + col
,右对角线的计算是n - col + row - 1
,如下所示:
3. 代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
| class Solution { private int[] cols; private int[] leftDiagonals; private int[] rightDiagonals; private int n; private int result;
public int totalNQueens(int n) { this.n = n; this.cols = new int[n]; this.leftDiagonals = new int[n * 2 - 1]; this.rightDiagonals = new int[n * 2 - 1]; helper(0); return result; }
private void helper(int row) { if (row == n) { result++; return; }
for (var col = 0; col < n; ++col) { if (allowLocate(row, col)) { cols[col] = 1; leftDiagonals[row + col] = 1; rightDiagonals[n - col + row - 1] = 1;
helper(row + 1);
cols[col] = 0; leftDiagonals[row + col] = 0; rightDiagonals[n - col + row - 1] = 0; } } }
private boolean allowLocate(int row, int col) { if (cols[col] == 1) { return false; }
if (leftDiagonals[row + col] == 1) { return false; }
if (rightDiagonals[n - col + row - 1] == 1) { return false; }
return true; } }
|
4. 复杂度
Author:
zchengb
License:
Copyright (c) 2019-2024 zchengb