N皇后II
1 题目详情
n 皇后问题 研究的是如何将 n 个皇后放置在 n × n 的棋盘上,并且使皇后彼此之间不能相互攻击。
给你一个整数 n ,返回 n 皇后问题 不同的解决方案的数量。
https://leetcode.cn/problems/n-queens-ii/
2 分析
刚一开始的时候我认为这道题很难,防止n个皇后在同一行这件事很容易,我们在递归的时候,每次调用递归函数,将当前放置的皇后的所在行标记为true,这样下一列我们在放皇后的时候,前面皇后的所在行都不能防止皇后。
但是难就难在,如何确定让皇后们不在同一条斜线上?
斜率为1的斜线,斜线上所有的皇后所在点的y-x
都是等值的。斜率为-1的斜线,斜线上所有的皇后所在点的x+y
都是等值的,我们只需要记录下当前步骤放置的皇后所在点的x+y
和x-y
的值,那么就相当于记录下了该皇后所在的两条斜线。
3 代码
class Solution {int res = 0;Set<Integer> sets1 = new HashSet<>(); // 记录斜率为1的斜线Set<Integer> sets2 = new HashSet<>(); // 记录斜率为-1的斜线public int totalNQueens(int n) {dfs(new boolean[n], n, 0);return res;}public void dfs(boolean[] visted_row, int n, int index) {if (index == n) { // index其实表示的是当前所在列res++;return;}for (int i = 0; i < n; i++) {if (visted_row[i]) continue;int real_row = i + 1; // yint real_col = index + 1; // xif (sets1.contains(real_row-real_col)) continue; if (sets2.contains(real_row+real_col)) continue; sets1.add(real_row-real_col); // 记录y-xsets2.add(real_row+real_col); // 记录y+xvisted_row[i] = true; dfs(visted_row, n, index + 1);visted_row[i] = false;sets1.remove(real_row-real_col); // 移除sets2.remove(real_row+real_col); // 移除}}
}
那么我们用同样的方法也可以做51. N 皇后,只需要在每次dfs的时候记录下当前皇后的坐标,最后创建n*n的棋盘,所有点置为.
,然后将皇后坐标置为Q
。
class Solution {List<List<String>> res = new ArrayList<>();Set<Integer> sets1 = new HashSet<>(); // 记录斜率为1的斜线Set<Integer> sets2 = new HashSet<>(); // 记录斜率为-1的斜线List<int[]> points = new ArrayList<>();List<List<int[]>> total_points = new ArrayList<>();public List<List<String>> solveNQueens(int n) {List<List<String>> res = new ArrayList<>();dfs(new boolean[n], n, 0);// 将total_points中的每个point_list变换成n*n的矩阵,有点的地方变成Q,没有点的地方变成.for (List<int[]> point_list : total_points) {char[][] matrix = new char[n][n];for (int i = 0; i < n; i++) {Arrays.fill(matrix[i], '.');}for (int[] point : point_list) {matrix[point[0]][point[1]] = 'Q';}List<String> matrix_str = new ArrayList<>();for (int i = 0; i < n; i++) {matrix_str.add(new String(matrix[i]));}res.add(matrix_str);}return res;}public void dfs(boolean[] visted_row, int n, int index) {if (index == n) { // index其实表示的是当前所在列total_points.add(new ArrayList<>(points));return;}for (int i = 0; i < n; i++) {if (visted_row[i]) continue;int real_row = i + 1; // yint real_col = index + 1; // xif (sets1.contains(real_row-real_col)) continue;if (sets2.contains(real_row+real_col)) continue;sets1.add(real_row-real_col); // 记录y-xsets2.add(real_row+real_col); // 记录y+xvisted_row[i] = true;points.add(new int[]{index, i});dfs(visted_row, n, index + 1);points.remove(points.size() - 1);visted_row[i] = false;sets1.remove(real_row-real_col); // 移除sets2.remove(real_row+real_col); // 移除}}
}