LeetCode_回溯_困难_51.N 皇后

谁借莪1个温暖的怀抱¢ 2023-10-06 18:58 165阅读 0赞

目录

  • 1.题目
  • 2.思路
  • 3.代码实现(Java)

1.题目

n 皇后问题 研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。给你一个整数 n ,返回所有不同的 n 皇后问题的解决方案。每一种解法包含一个不同的 n 皇后问题 的棋子放置方案,该方案中 ‘Q’ 和 ‘.’ 分别代表了皇后和空位。

示例1:
在这里插入图片描述

输入:n = 4
输出:[[“.Q…”,“…Q”,“Q…”,“…Q.”],[“…Q.”,“Q…”,“…Q”,“.Q…”]]
解释:如上图所示,4 皇后问题存在两个不同的解法。

示例 2:
输入:n = 1
输出:[[“Q”]]

提示:
1 <= n <= 9
皇后彼此不能相互攻击,也就是说:任何两个皇后都不能处于同一条横行、纵行或斜线上。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/n-queens

2.思路

(1)回溯算法

  • 为了方便求解题目,可以先用数组来保存每种结果,然后再将其转化为字符串,保存到 list 数组中。一般来说,由于棋盘是二维的,故可以考虑使用二维数组来保存每个皇后的位置,但是考虑到题目中皇后位置的特殊性,一行只能放置一个皇后(即可以看作第 i 个皇后肯定放置在第 i 行),故可以考虑在此前提下,使用长度为 n + 1 一维数组 x[] 保存每种结果以节省存储空间,即设 x[i] 表示第 i 个皇后放在棋盘的第i行的第 x[i] 列,其中1 ≤ i ≤ n。此外还需创建保存所有结果的 list 数组 res;
  • 本题使用回溯法的基本思想是:使用递归函数 backTrack(1, n, x) 实现对整个解空间的回溯搜索,backTrack(i, n, x) 搜索解空间的第 i 层子树(即可看作搜索适合第 i 个皇后放置的位置):

    • 当 i > n 时,算法搜索至叶结点,得到了一个新的 n 皇后互不攻击的放置方案,并且将其保存到 res 中;
    • 当 i ≤ n 时,该结点有 n 个儿子结点 x[i](第 i 个皇后在第 i 行有 n 个列的位置可以放置),对于每个位置,使用 place() 方法来检查其可行性,又由于前提是一行只放置一个皇后,所以在 place() 方法中只需判断纵行方向与斜线方向上是否有其它皇后即可。
  • 当回溯结束后,返回 res 即可。

相关题目:
LeetCode_回溯_困难_52.N皇后 II

3.代码实现(Java)

  1. //思路1————回溯法
  2. class Solution {
  3. List<List<String>> res = new ArrayList<>();
  4. public List<List<String>> solveNQueens(int n) {
  5. // queens[t] 表示第 t 个皇后放在棋盘的第 t 行的第 queens[t] 列 (0 ≤ t < n)
  6. int[] queens = new int[n];
  7. backtrack(queens, 0);
  8. return res;
  9. }
  10. public void backtrack(int[] queens, int t) {
  11. int n = queens.length;
  12. if (t == n) {
  13. List<String> tmpRes = new ArrayList<>();
  14. //将结果保存到 res 中
  15. for (int i = 0; i < n; i++) {
  16. StringBuilder str = new StringBuilder();
  17. for (int j = 0; j < n; j++) {
  18. if (j == queens[i]) {
  19. str.append("Q");
  20. } else {
  21. str.append(".");
  22. }
  23. }
  24. tmpRes.add(str.toString());
  25. }
  26. res.add(tmpRes);
  27. return;
  28. }
  29. for (int i = 0; i < n; i++) {
  30. //将第 t 个皇后放在棋盘的第 t 行的第 queens[t] 列
  31. queens[t] = i;
  32. //判断第 t 个皇后能不能放在当前位置
  33. if (check(queens, t)) {
  34. //如果能够放在当前位置,则开始判断下一个皇后
  35. backtrack(queens, t + 1);
  36. }
  37. }
  38. }
  39. //在一行只放一个皇后的前提下,判断第 t 个皇后能否放在当前位置
  40. public boolean check(int[] queens, int t) {
  41. //判断当前第 t 个皇后是否与前 0 ~ t - 1 行的皇后能相互攻击
  42. for (int i = 0; i < t; i++) {
  43. /*
  44. t - i == Math.abs(queens[i] - queens[t]): 判断当前第 t 个皇后是否之前的第 i 个皇后在同一斜线上
  45. queens[i] == queens[t]: 判断当前第 i 个皇后是否之前的第 t 个皇后在同一纵行上
  46. */
  47. if ((t - i) == Math.abs(queens[i] - queens[t]) || queens[i] == queens[t]) {
  48. return false;
  49. }
  50. }
  51. return true;
  52. }
  53. }

发表评论

表情:
评论列表 (有 0 条评论,165人围观)

还没有评论,来说两句吧...

相关阅读

    相关 LeetCode 51. N皇后

    题目重述 n 皇后问题 研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。 给你一个整数 n ,返回所有不同的 n 皇后问题 的解决方

    相关 leetcode:51. N皇后

    题目: n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。 上图为 8 皇后问题的一种解法。 给定一个整数 n,返回所有

    相关 Leetcode51N皇后

    n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。 思路: 刚开始的思路是,用一个二维int数组来保存,后来发现很繁琐,其次就