📣 Back to School开学季 - VIP通行证5折优惠!蓝莓、Offer多多同步优惠
查看: 1270| 回复: 3
跳转到指定楼层
上一主题 下一主题
收起左侧

[二分/排序/搜索] 求讨论 n皇后的非递归解法

全局:

注册一亩三分地论坛,查看更多干货!

您需要 登录 才可以下载或查看附件。没有帐号?注册账号

x
LC51题N皇后

是一道dfs的经典题了,暴力DFS递归,优化的DFS写过,今天下午想用暴力非递归解法写,先自己想写了如下代码(Java),没有ac,应该是思路有些问题。有同做题的同学,可以帮忙看看思路哪里出现了问题吗?

思路:
- 把 要遍历的 N * N的棋盘,看成是 N 棵树(不是严格意义上的树)。为什么这样想呢?我想根据dfs的非递归写法来改写,在dfs的非递归写法中,是从树的root一个节点开始做dfs的。所以这里我把棋盘的第一行N个位置,看作是N个root。然后从每个root开始对以这个root为根的树做dfs的非递归coding。
- 和原始的dfs不同的一点在于,遍历到一个节点的时候需要知道该节点是在哪一行上,所以使用了变量level来记录
- count[level]是来记录当前level上还有多少个节点没有遍历,如果遍历完了就要向上回溯level--

发现问题的大佬,加6米(你发三条评论,每条我能加2)


  1. public class Solution {
  2.     /*
  3.      * @param n: The number of queens
  4.      * @return: All distinct solutions
  5.      */

  6.     private Stack<Integer> stack = new Stack<>();
  7.     public List<List<String>> solveNQueens(int n) {
  8.         List<List<String>> results = new ArrayList<>();

  9.         if (n <= 0) {
  10.             return results;
  11.         }

  12.         int[] oneRes = new int[n];

  13.         // 共有n个root节点
  14.         for (int i = 0; i < n; i++) {
  15.             stack.push(i); // push root i (一个节点)
  16.             int[] count = new int[n];
  17.             int level = 0;
  18.             count[level] = 1;
  19.             while (!stack.isEmpty()) {
  20.                 int node = stack.pop();
  21.                 count[level]--;
  22.                 // process node
  23.                 boolean available = isAvailable(n, oneRes, level, node);


  24.                 if (available) {
  25.                     oneRes[level] = node;
  26.                     if (level + 1 < n) {
  27.                         // nodes: 0, 1, 2, ..., n-1
  28.                         // stack.push(nodes);
  29.                         level++;
  30.                         count[level] = n;
  31.                         for (int j = 0; j < n; j++) {
  32.                             stack.push(j);
  33.                         }
  34.                     } else {
  35.                         results.add(drawChessboard(oneRes));
  36.                     }
  37.                 }


  38.                 if (count[level] == 0) {
  39.                     level--;
  40.                 }
  41.             }

  42.         }


  43.         return results;
  44.     }


  45. private List<String> drawChessboard(int[] cols) {
  46.         List<String> chessboard = new ArrayList<>();
  47.         for (int i = 0; i < cols.length; i++) {
  48.             StringBuilder sb = new StringBuilder();
  49.             for (int j = 0; j < cols.length; j++) {
  50.                 sb.append(j == cols[i] ? 'Q' : '.');
  51.             }
  52.             chessboard.add(sb.toString());
  53.         }
  54.         return chessboard;
  55.     }

  56.     private boolean isAvailable(int n, int[] queen, int row, int col) {
  57.          for (int i = 1; row - i >= 0; i++) {
  58.             int prevQ = queen[row - i];
  59.             if (col == prevQ) {
  60.                 return false;
  61.             }
  62.             if (col - i >= 0 && col - i == prevQ) {
  63.                 return false;
  64.             }
  65.             if (col + i < n && col + i == prevQ) {
  66.                 return false;
  67.             }
  68.         }
  69.         return true;
  70.     }
  71. }
复制代码



have 刷题 smooth day!



上一篇:通信工程秋招在哪里刷题做准备?
下一篇:微软近期高频面试题分享 + 分析(四)
推荐
 楼主| 我是Kanade 2021-5-10 21:34:50 | 只看该作者
全局:
错误原因是:
当某层的所有col位置用完了,我们要向上回溯的时候,可能不是仅仅level--向上只减一那么简单。比如
[x, ?, ?]
[x, x, x]
[x, x, x]
row: based-0-index, col: based-0-index
x 表示已经试过,? 表示没有试过。现在假设刚试完[2,2]位置上的col,此时row == 2的这层都试完了。此时向上回溯,我们应该回溯到row == 0 而不是 row == 1.
应该回溯的level 是 count数组从右向左数第一个非0的index.

改正后可以ac的代码:

  1. public class Solution {
  2.     /*
  3.      * @param n: The number of queens
  4.      * @return: All distinct solutions
  5.      */

  6.     private Stack<Integer> stack = new Stack<>();
  7.     public List<List<String>> solveNQueens(int n) {
  8.         List<List<String>> results = new ArrayList<>();

  9.         if (n <= 0) {
  10.             return results;
  11.         }

  12.         int[] oneRes = new int[n];

  13.         // 共有n个root节点
  14.         
  15.         int[] count = new int[n];
  16.         for (int i = 0; i < n; i++) {
  17.             stack.push(i);
  18.         }

  19.         int level = 0;
  20.         count[level] = n;

  21.         while (!stack.isEmpty()) {
  22.             int col = stack.pop();
  23.             
  24.             count[level]--;
  25.             // process col
  26.             boolean available = isAvailable(n, oneRes, level, col);


  27.             if (available) {
  28.                 oneRes[level] = col;
  29.                 if (level + 1 < n) {
  30.                     // cols: 0, 1, 2, ..., n-1
  31.                     // stack.push(cols);
  32.                     level++;
  33.                     count[level] = n;
  34.                     for (int j = 0; j < n; j++) {
  35.                         stack.push(j);
  36.                     }
  37.                 } else if (level + 1 == n){
  38.                     results.add(drawChessboard(oneRes));
  39.                 }
  40.             }


  41.             if (count[level] == 0) {
  42.                 // level--;
  43.                 level = updateLevel(count, level);
  44.             }
  45.         }

  46.         



  47.         return results;
  48.     }

  49.     private int updateLevel(int[] count, int curLevel) {
  50.         int i = curLevel;
  51.         while (i >= 1) {
  52.             if (count[--i] != 0) break;
  53.         }
  54.         return i;
  55.     }


  56. private List<String> drawChessboard(int[] cols) {
  57.         List<String> chessboard = new ArrayList<>();
  58.         for (int i = 0; i < cols.length; i++) {
  59.             StringBuilder sb = new StringBuilder();
  60.             for (int j = 0; j < cols.length; j++) {
  61.                 sb.append(j == cols[i] ? 'Q' : '.');
  62.             }
  63.             chessboard.add(sb.toString());
  64.         }
  65.         return chessboard;
  66.     }

  67.     private boolean isAvailable(int n, int[] queen, int row, int col) {
  68.          for (int i = 1; row - i >= 0; i++) {
  69.             int prevQ = queen[row - i];
  70.             if (col == prevQ) {
  71.                 return false;
  72.             }
  73.             if (col - i >= 0 && col - i == prevQ) {
  74.                 return false;
  75.             }
  76.             if (col + i < n && col + i == prevQ) {
  77.                 return false;
  78.             }
  79.         }
  80.         return true;
  81.     }
  82. }

复制代码

评分

参与人数 2大米 +4 收起 理由
Phenomenon. + 1 赞一个
14417335 + 3

查看全部评分

回复

使用道具 举报

🔗
 楼主| 我是Kanade 2021-5-10 18:11:01 | 只看该作者
全局:
我debug出来了!如果已经有look into的同学,不明白的可以私聊我!
回复

使用道具 举报

全局:
求刷题的经验和方法zszs感谢🙏
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册账号
隐私提醒:
  • ☑ 禁止发布广告,拉群,贴个人联系方式:找人请去🔗同学同事飞友,拉群请去🔗拉群结伴,广告请去🔗跳蚤市场,和 🔗租房广告|找室友
  • ☑ 论坛内容在发帖 30 分钟内可以编辑,过后则不能删帖。为防止被骚扰甚至人肉,不要公开留微信等联系方式,如有需求请以论坛私信方式发送。
  • ☑ 干货版块可免费使用 🔗超级匿名:面经(美国面经、中国面经、数科面经、PM面经),抖包袱(美国、中国)和录取汇报、定位选校版
  • ☑ 查阅全站 🔗各种匿名方法

本版积分规则

>
快速回复 返回顶部 返回列表