【问题描述】[困难]

【解答思路】

1. 主副对角线列 标记

复杂度

import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Deque;
import java.util.List;public class Solution {private int n;// 记录某一列是否放置了皇后private boolean[] col;// 记录主对角线上的单元格是否放置了皇后private boolean[] main;// 记录了副对角线上的单元格是否放置了皇后private boolean[] sub;private List<List<String>> res;public List<List<String>> solveNQueens(int n) {res = new ArrayList<>();if (n == 0) {return res;}// 设置成员变量,减少参数传递,具体作为方法参数还是作为成员变量,请参考团队开发规范this.n = n;this.col = new boolean[n];this.main = new boolean[2 * n - 1];this.sub = new boolean[2 * n - 1];Deque<Integer> path = new ArrayDeque<>();dfs(0, path);return res;}private void dfs(int row, Deque<Integer> path) {if (row == n) {// 深度优先遍历到下标为 n,表示 [0.. n - 1] 已经填完,得到了一个结果List<String> board = convert2board(path);res.add(board);return;}// 针对下标为 row 的每一列,尝试是否可以放置for (int j = 0; j < n; j++) {if (!col[j] && !main[row + j] && !sub[row - j + n - 1]) {path.addLast(j);col[j] = true;main[row + j] = true;sub[row - j + n - 1] = true;dfs(row + 1, path);// 递归完成以后,回到之前的结点,需要将递归之前所做的操作恢复sub[row - j + n - 1] = false;main[row + j] = false;col[j] = false;path.removeLast();}}}private List<String> convert2board(Deque<Integer> path) {List<String> board = new ArrayList<>();for (Integer num : path) {StringBuilder row = new StringBuilder();row.append(".".repeat(Math.max(0, n)));row.replace(num, num + 1, "Q");board.add(row.toString());}return board;}
}

其实已经摆放皇后的列下标、占据了哪一条主对角线、哪一条副对角线也可以使用哈希表来记录。

实际上哈希表底层也是数组,使用哈希表可以不用处理已经占据位置的皇后的主对角线、副对角线的下标偏移问题。

import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Deque;
import java.util.HashSet;
import java.util.List;
import java.util.Set;public class Solution {private Set<Integer> col;private Set<Integer> main;private Set<Integer> sub;private int n;private List<List<String>> res;public List<List<String>> solveNQueens(int n) {this.n = n;res = new ArrayList<>();if (n == 0) {return res;}col = new HashSet<>();main = new HashSet<>();sub = new HashSet<>();Deque<Integer> path = new ArrayDeque<>();dfs(0, path);return res;}private void dfs(int row, Deque<Integer> path) {if (row == n) {List<String> board = convert2board(path);res.add(board);return;}// 针对每一列,尝试是否可以放置for (int i = 0; i < n; i++) {if (!col.contains(i) && !main.contains(row + i) && !sub.contains(row - i)) {path.addLast(i);col.add(i);main.add(row + i);sub.add(row - i);dfs(row + 1, path);sub.remove(row - i);main.remove(row + i);col.remove(i);path.removeLast();}}}private List<String> convert2board(Deque<Integer> path) {List<String> board = new ArrayList<>();for (Integer num : path) {StringBuilder row = new StringBuilder();row.append(".".repeat(Math.max(0, n)));row.replace(num, num + 1, "Q");board.add(row.toString());}return board;}
}
2. board[n][n]标记 直接遍历

时间复杂度:O(N!) 空间复杂度:O(N2)

class Solution {List<List<String>> res=new ArrayList<>();public List<List<String>> solveNQueens(int n) {//棋盘,默认为0表示空,1表示皇后int[][] borad = new int[n][n];//row当前填写得的行号dfs(n,0,borad);return res;}public void dfs(int n,int row,int[][] board) { if (row == n) { // n个棋子都放置好了,打印结果 res.add(track(board,n));// n行棋子都放好了,已经没法再往下递归了,所以就return } return; }for (int column = 0; column < n; ++column) { // 每一行都有8中放法 if (isOk(row, column,n,board)) { // 有些放法不满足要求             board[row][column] =1; dfs( n,row+1,board); // 考察下一行board[row][column] =0;} }}private boolean isOk(int row ,int column ,int n,int[][] board){int leftup = column -1,rightup = column+1;for(int i=row-1;i>=0;i--){// 逐行往上考察每一行if(board[i][column]==1){// 第i行的column列有棋子吗?return false;}if(leftup>=0){// 考察左上对角线:第i行leftup列有棋子吗?if(1==board[i][leftup])return false;}if(rightup<n){// 考察右上对角线:第i行rightup列有棋子吗?if(1==board[i][rightup])return false;}leftup--;rightup++;}return true;}private List<String> track(int[][] board, int n) {// 打印出一个二维矩阵List<String> list=new ArrayList<>();for (int row = 0; row < n; ++row) { StringBuffer str = new StringBuffer();for (int column = 0; column < n; ++column) { if (board[row][column] == 1){str.append("Q");}else{str.append(".");} }list.add(str.toString());} return list;}
}

【总结】

1.回溯模板
List<> res = new LinkedList<>();
Deque<Integer> path =  new ArrayDeque<>();void dfs(路径, 选择列表){if 满足结束条件{res.add(路径);return;}for 选择 in 选择列表{// 做选择;// 标记一下已经选了,有些题目不需要标记nums[i] = true;// 把选择的放进路径path.push(i)dfs(路径, 选择列表);// 恢复现场;path.pop();nums[i] = false;}
}
2.回溯思想

【数据结构与算法】【算法思想】回溯算法

转载链接:https://leetcode-cn.com/problems/n-queens/solution/gen-ju-di-46-ti-quan-pai-lie-de-hui-su-suan-fa-si-/
转载链接:https://leetcode-cn.com/problems/n-queens/solution/java-hui-su-xiang-xi-zhu-jie-bu-tong-fang-fa-pan-d/

[Leetcode][第81题][JAVA][N皇后问题][回溯算法]相关推荐

  1. [Leetcode][第78题][JAVA][子集][位运算][回溯]

    [问题描述][中等] [解答思路] 1. 位运算 复杂度 class Solution {List<Integer> t = new ArrayList<Integer>(); ...

  2. [Leetcode][第79题][JAVA][单词搜索][DFS][回溯]

    [问题描述][中等] [解答思路] 1. DFS繁琐版本 class Solution {public boolean exist(char[][] board, String word) {bool ...

  3. [Leetcode][第40题][JAVA][数组总和2][回溯][剪枝]

    [问题描述][中等] [解答思路] 1. 减法 import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Ar ...

  4. [Leetcode][第216题][JAVA][数组之和3][回溯]

    [问题描述][中等] [解答思路] 回溯 剪树枝 当和超过n 或 个数超过k 1. 正向求和 优化前 class Solution {public List<List<Integer> ...

  5. [Leetcode][第17题][JAVA][电话号码的字母组合][回溯]

    [问题描述][中等] [解答思路] 用哈希表/数组存储每个数字对应的所有可能的字母,然后进行回溯操作. 回溯过程中维护一个字符串,表示已有的字母排列(如果未遍历完电话号码的所有数字,则已有的字母排列是 ...

  6. [Leetcode][第679题][JAVA][24点游戏][回溯][暴力]

    [问题描述][困难] [解答思路] 回溯 时间复杂度:O(1) 空间复杂度:O(1) class Solution {static final int TARGET = 24;static final ...

  7. [Leetcode][第39题][JAVA][组合总和][回溯][dfs][剪枝]

    [问题描述][中等] [解答思路] 1. 回溯 import java.util.ArrayDeque; import java.util.ArrayList; import java.util.De ...

  8. [Leetcode][第77题][JAVA][组合][回溯]

    [问题描述][中等] [解答思路] 1. 回溯 class Solution {List<List<Integer>> lists = new ArrayList<> ...

  9. [Leetcode][第889题][JAVA][根据前序和后序遍历构造二叉树][分治][递归]

    [问题描述][中等] [解答思路] copyOfRange class Solution {public TreeNode constructFromPrePost(int[] pre, int[] ...

最新文章

  1. java 注解继承注解_Java注解合并,注解继承
  2. c语言double变量后面几个0,C语言double型变量的初始化到底是是0还是0.0?
  3. ESXI开启snmp协议方法
  4. css列表格式属性,css list-style-type属性笔记
  5. python中计算排队等待时间_codewars(python)练习笔记十:计算超市排队时长
  6. HTML+CSS+JS实现 ❤️绘制卡丁车动漫特效❤️
  7. 添加作者_卤肉,有“添加剂”才香?大错特错,没有这5种香料,什么味道都没有...
  8. 基于java洗浴中心管理系统_Java小白也能听懂的线程池的内部原理:老王的洗浴中心...
  9. 神经网络技巧篇之寻找最优参数的方法
  10. Zabbix(三)zabbix平台添加服务监控选项(http、nginx、mysql)
  11. 新买阿里云linux服务器如何设置账号密码xshell远程登陆
  12. 动态系统建模与仿真 基本知识笔记(源自DR_CAN)
  13. Ubuntu/Linux/Unix 究竟有什么区别??
  14. jpa 动态查询条件 数组_JPA使用Specification构建动态查询
  15. 胡闹厨房2 for Mac厨房模拟游戏又名煮糊了2
  16. 批量删除html网页,ie浏览器收藏夹网页批量删除方法
  17. python解决微分方程(数值解法)
  18. 【unity中运行HTC VIVE的案例场景时一直不显示在头盔上,VR其他都正常】
  19. 亚马逊继续“激进” :Q3吐出超10倍净利
  20. 阿翔编程学-Axis传递Pojo对象

热门文章

  1. HDU 1402 A * B Problem Plus FFT
  2. 苏教版国标本小学语文第一册汉字笔画
  3. 解析IP地址与MAC地址
  4. sharepoint安装心得_过程
  5. Python爬虫自学之第(②)篇——BeautifulSoup解析网页
  6. Mybatis源码学习笔记
  7. Android中WebService的应用
  8. 微信小程序开发实战基础一、页面跳转,底部导航栏,分享,加载图片标签,列表
  9. wmode解决flash透明及层深问题
  10. mysql保存plc数据_MySQL空间数据的保存