八皇后时间复杂度_【算法打卡】N皇后
难度:困难
题目:
n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。
上图为 8 皇后问题的一种解法。
给定一个整数 n,返回 n 皇后不同的解决方案的数量。
提示:
皇后,是国际象棋中的棋子,意味着国王的妻子。皇后只做一件事,那就是“吃子”。当她遇见可以吃的棋子时,就迅速冲上去吃掉棋子。
当然,她横、竖、斜都可走一或 N-1 步,可进可退。(引用自 百度百科 - 皇后 )
--------------------------------------------
N皇后问题,经典的题目,记得大学老师很喜欢用来做教学题材,回溯法的入门经典教学用例,8皇后。
只不过这里不是8皇后,是N个皇后,其实做法都大同小异,只不过一个是写死8个皇后,一个是支持输入而已。
N皇后问题应该有耳朵的都听过了吧。
就是如果当前皇后所在位置,如果上下左右外加 斜上下左右的,已经有存在皇后的话,那就是冲突,就不能放,只能找其他位置。
5皇后例子
如果能找到符合需求的n个皇后都完美放在了棋盘中的话,那就是一个完美的答案,现在需要把所有的答案打印出来,皇后的位置是“Q”,其他空位置为“.”表示。
这是回溯法的专用教学案例,当然这里也是使用回溯法。
回溯法基本思想就是:
回溯法(探索与回溯法)是一种选优搜索法,又称为试探法,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为“回溯点”。
其实回溯法在之前的《将数组拆分成斐波那契序列》中也有用到,但是那个还不够经典。
归于当前需求,并结合回溯法思想,也就是找到每行的每一个皇后在哪一列来确定他的坐标[i, j]。
这里我按列来说。
从第一列的第一行开始,判断之前的列有没冲突,如果有就向下走一格,如果没有就放下。
继续判断第二列的皇后。
。
。
当到了第n列时,如果这列的皇后放在第x行刚好和之前的没有冲突,那就是一个答案,然后再向下找(当然已经没有了,因为每一次到最后一列只有一个答案)。
那最后一列的已经找到了最后一行了呢,那就来了,回溯。
退回到前一列(第n-1列),然后前一列的皇后继续往下面的行移动,如果找到了再继续后一列(第n列)的判断。如果没有就再回溯,回到了n-2列,然后同理的操作。
当退回到第1列时,全都试探完了,那就是完了。
这里还可以优化了一下,把二维数组换成了单维数组,i-n和a[i]分别代表行和列。
递归实现:
public List> solveNQueens(int n) { List> solutions = new ArrayList>(); int[] queens = new int[n]; Arrays.fill(queens, -1); Set columns = new HashSet(); Set diagonals1 = new HashSet(); Set diagonals2 = new HashSet(); backtrack(solutions, queens, n, 0, columns, diagonals1, diagonals2); return solutions;}public void backtrack(List> solutions, int[] queens, int n, int row, Set columns, Set diagonals1, Set diagonals2) { if (row == n) { List board = generateBoard(queens, n); solutions.add(board); } else { for (int i = 0; i < n; i++) { if (columns.contains(i)) { continue; } int diagonal1 = row - i; if (diagonals1.contains(diagonal1)) { continue; } int diagonal2 = row + i; if (diagonals2.contains(diagonal2)) { continue; } queens[row] = i; columns.add(i); diagonals1.add(diagonal1); diagonals2.add(diagonal2); backtrack(solutions, queens, n, row + 1, columns, diagonals1, diagonals2); queens[row] = -1; columns.remove(i); diagonals1.remove(diagonal1); diagonals2.remove(diagonal2); } }}public ListgenerateBoard(int[] queens, int n) { List board = new ArrayList(); for (int i = 0; i < n; i++) { char[] row = new char[n]; Arrays.fill(row, '.'); row[queens[i]] = 'Q'; board.add(new String(row)); } return board;}
时间复杂度:O(n的n次方)
空间复杂度:O(n+x)
非递归实现:
class Solution { public List> solveNQueens(int n) { List> lists = new ArrayList<>(); int i = 1; // 用数组a存储棋子坐标,可以理解为i代表列,a[i]代表行 int[] a = new int[n+1]; while (i > 0) { // i为当前列,寻找前面各列与当前第i列的排斥情况,拿到的a[i]就是当前行i的合适a[i]列 for (a[i]++; a[i]<=n; a[i]++) if (check2(a, i)) break; // 如果a[i]列小于n,则可以继续向后找 if (a[i] <= n) { // 如果当前行i就是第n行,则数量加1 if (i == n) { Listlist = new ArrayList<>(); for (int i2 : a) { StringBuilder sb = new StringBuilder(); for (int j = 0; j < n; j++) { if (j + 1 == i2) sb.append("Q"); else sb.append("."); } list.add(sb.toString()); } list.remove(0); lists.add(list); // 否则就是向后一列找,并且后面一列无论是有没找过都要重置为0; } else { i++; a[i] = 0; } // 否则就是回溯,回到前一列(然后继续向下面行找) } else { i--; } } return lists; } private static boolean check2(int[] a, int n) { for (int i=1; i if (Math.abs(a[i]-a[n])==Math.abs(i-n) || a[i]==a[n]) return false; } return true; }}
时间复杂度:O(n!)
空间复杂度:O(n+x)
-----------------------------------未完-----------------------------------
后面还有一个八皇后II,其实也就是大同小异,上面的是打印出棋盘,这个II就是计算个数(??这特么有啥区别?)
所以直接贴代码了。
递归实现:
public int totalNQueens(int n) { Set columns = new HashSet(); Set diagonals1 = new HashSet(); Set diagonals2 = new HashSet(); return backtrack(n, 0, columns, diagonals1, diagonals2);}public int backtrack(int n, int row, Set columns, Set diagonals1, Set diagonals2) { if (row == n) { return 1; } else { int count = 0; for (int i = 0; i < n; i++) { if (columns.contains(i)) { continue; } int diagonal1 = row - i; if (diagonals1.contains(diagonal1)) { continue; } int diagonal2 = row + i; if (diagonals2.contains(diagonal2)) { continue; } columns.add(i); diagonals1.add(diagonal1); diagonals2.add(diagonal2); count += backtrack(n, row + 1, columns, diagonals1, diagonals2); columns.remove(i); diagonals1.remove(diagonal1); diagonals2.remove(diagonal2); } return count; }}
时间复杂度:O(n的n次方)
空间复杂度:O(n)
非递归实现:
public static int totalNQueens(int n) { int count = 0, i = 1; // 用数组a存储棋子坐标,可以理解为i代表列,a[i]代表行 int[] a = new int[n+1]; while (i > 0) { // i为当前列,寻找前面各列与当前第i列的排斥情况,拿到的a[i]就是当前行i的合适a[i]列 for (a[i]++; a[i]<=n; a[i]++) if (check2(a, i)) break; // 如果a[i]列小于n,则可以继续向后找 if (a[i] <= n) { // 如果当前行i就是第n行,则数量加1 if (i == n) { count++; // 否则就是向后一列找,并且后面一列无论是有没找过都要重置为0; } else { i++; a[i] = 0; } // 否则就是回溯,回到前一列(然后继续向下面行找) } else { i--; } } return count;}private static boolean check2(int[] a, int n) { for (int i=1; i if (Math.abs(a[i]-a[n])==Math.abs(i-n) || a[i]==a[n]) return false; } return true;}
时间复杂度:O(n!)
空间复杂度:O(n)
需要注意的是,递归的回溯法是一颗全部展开的树,时间复杂度是N的N次方,很灵恐怖,虽然好理解,但是还是建议用迭代法。
--------------------------------------------完--------------------------------------------
当我望向你的时候,多希望你也在看着我。
八皇后时间复杂度_【算法打卡】N皇后相关推荐
- 八皇后时间复杂度_回溯算法 | 追忆那些年曾难倒我们的八皇后问题
文章收录在公众号:bigsai,关注更多干货和学习资源 记得点赞.在看 前言 说起八皇后问题,它是一道回溯算法类的经典问题,也可能是我们大部分人在上数据结构或者算法课上遇到过的最难的一道题-- 在这里 ...
- 八皇后时间复杂度_九章算法 | N皇后问题
n皇后问题是将n个皇后放置在n*n的棋盘上,皇后彼此之间不能相互攻击(任意两个皇后不能位于同一行,同一列,同一斜线). 给定一个整数n,返回所有不同的n皇后问题的解决方案. 每个解决方案包含一个明确的 ...
- 八皇后时间复杂度_【精神分裂症】首次发病未治疗精神分裂症患者大脑皮质复杂度改变...
点击标题下「蓝色微信名」可快速关注 文章来源:中华精神科杂志,2020,53 (01): 11-15 作者:魏巍 邓伟 周燚 彭祖贵 何韬 吕秋玥 李涛 摘要摘要 目的 探讨首次发病未治疗精神分裂症患 ...
- java中怎么计算算法的时间复杂度_算法的时间复杂度和空间复杂度计算
一.算法的时间复杂度定义 在进行算法分析时,语句总的执行次数T(n)是关于问题规模n的函数,进而分析T(n)随n的变化情况并确定T(n)的数量级.算法的时间复杂度,也就是算法的时间量度.记作:T(n) ...
- a*算法的时间复杂度_算法基础——时间复杂度amp;空间复杂度
关注.星标公众号,学点计算机知识. 整理:persistenceBin 今天来跟大家继续分享一下数据结构的基础知识--算法效率的度量:时间复杂度和空间复杂度.首先来跟大家分享一下在电影<复仇者联 ...
- 排序算法的时间复杂度_算法的时间复杂度
一. 算法的时间复杂度 1.如何评估算法的性能 数据结构和算法,本质上是解决现实存在的问题,即如何让解决指定问题的代码运行得更快?一个算法如果能在所要求的资源限制(resource constrain ...
- a*算法的时间复杂度_算法的时间和空间复杂度,就是这么简单
算法(Algorithm) 算法是程序用来操作数据.解决程序问题的一组方法.对于同一个问题,使用不同的算法,也许最终得到的结果是一样的,但在过程中消耗的资源和时间却会有很大的区别. 那么我们应该如何去 ...
- 一层循环时间复杂度_算法的时间与空间复杂度(一看就懂)
算法(Algorithm)是指用来操作数据.解决程序问题的一组方法.对于同一个问题,使用不同的算法,也许最终得到的结果是一样的,但在过程中消耗的资源和时间却会有很大的区别. 那么我们应该如何去衡量不同 ...
- a*算法的时间复杂度_算法的时间复杂度:大O表示法
本文讨论一下算法的时间复杂度问题,用到的素材取自<算法图解>一书,强烈推荐, 如有不妥,请联系我! 二分查找 随便想一个1-100的数字. 你的目标是以最少的次数猜到这个数字.你每次猜测后 ...
最新文章
- Golang 入门系列(十) mysql数据库的使用
- JavaFX学习之道:JavaFX之TableView
- 如何用Excel统计出各科指定分数段的人数?(亲测)
- Android与Linux以及GNU的关系
- django 数据库中中文转化为汉语拼音
- C# 中 System.Index 结构体和 Hat 运算符(^)的全新用法
- Codeforces Round #592 (Div. 2) F. Chips 构造 + 细节
- webstorm的debug模式
- Understanding the Bias-Variance Tradeoff
- linux零拷贝 nio,荐 面试题:NIO/Netty 中的零拷贝体现在哪里?
- 计算机随机数是如何生成的?(平分取中法、线性同余法)
- 图像拼接——APAP算法
- teststand调用python模块_TestStand 界面重置【小技巧】
- python打开qq并登录_python爬虫入门之qq登陆初探
- Mac系统安装consul
- 冲刺大厂每日算法面试题,动态规划21天——第七天
- 第二届中国(泰州)国际装备高层次人才创新创业大赛
- 记PMP 考试2021/06/20总结(含笔记)
- MySQL:查询每个部门的员工小时平均工资(显示部门名称、部门员工小时平均 工资)
- 用 Python 写个俄罗斯方块小游戏
热门文章
- ssm框架逻辑删除mysql_MybatisPlus--CRUD接口及主键增长策略、自动填充、乐观锁更新数据...
- ftp服务器上传文件提示451,解决IIS7之FTP部分文件上传451错误
- 快手用旺旺瓶子做机器人_100品牌入榜,在快手的品牌运营怎么做?|11月快手品牌新势力榜揭晓...
- 教你玩转CSS Overflow
- canvas 圆角矩形填充_一篇文章让你学会你最“害怕”的Canvas,太有意思了
- node那点事(二) -- Writable streams(可写流)、自定义流
- 只需5步,轻松创建HTML5离线应用
- css动画-模拟正余弦曲线
- BZOJ1706奶牛接力跑
- selenium3 + python - cookie定位