八皇后时间复杂度_【算法打卡】N皇后

caff2e3673d22bc13f6b5620bafc1540.png

难度:困难

题目:

    n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。

a6b1f951c35d8db5f7fb7c506b20542e.png

    上图为 8 皇后问题的一种解法。

    给定一个整数 n,返回 n 皇后不同的解决方案的数量。

7645eb8bd493ed36897380da3af9edd1.png

提示:

    皇后,是国际象棋中的棋子,意味着国王的妻子。皇后只做一件事,那就是“吃子”。当她遇见可以吃的棋子时,就迅速冲上去吃掉棋子。

    当然,她横、竖、斜都可走一或 N-1 步,可进可退。(引用自 百度百科 - 皇后 )

--------------------------------------------

    N皇后问题,经典的题目,记得大学老师很喜欢用来做教学题材,回溯法的入门经典教学用例,8皇后。

    只不过这里不是8皇后,是N个皇后,其实做法都大同小异,只不过一个是写死8个皇后,一个是支持输入而已。

    N皇后问题应该有耳朵的都听过了吧。

    就是如果当前皇后所在位置,如果上下左右外加 斜上下左右的,已经有存在皇后的话,那就是冲突,就不能放,只能找其他位置。

9a03ebbe3db2578d3914438daf28afee.png

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次方,很灵恐怖,虽然好理解,但是还是建议用迭代法。

--------------------------------------------完--------------------------------------------

当我望向你的时候,多希望你也在看着我。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/373912.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Android-Binder 简析

前言 对于Android来说&#xff0c;Binder的重要性怎么说都不为过。不管是我们的四大组件Activity、Service、BroadcastReceiver、ContentProvider&#xff0c;还是经常在应用中使用到的各种ServiceManager&#xff0c;其背后都是Binder在支撑。然而Binder机制又不是三言两语能够…

tplink 703刷固件

1.软件下载: ImageBuilder链接 如果是全新刷机的话,使用:http://downloads.openwrt.org/snapshots/trunk/ar71xx/generic/openwrt-ar71xx-generic-tl-wr703n-v1-squashfs-factory.bin 如果是系统升级的话,使用:http://downloads.openwrt.org/snapshots/trunk/ar71xx/generic/op…

编程反模式

您是否曾经进行过代码审查&#xff0c;记录了非常高的WTF / m&#xff1f; 您是否想知道所有这些错误代码的原因是什么&#xff1f; 在大多数情况下&#xff0c;导致原因1的主要原因是使用设计和编码反模式。 如果您喜欢定义&#xff0c;请参见以下内容&#xff1a;AntiPatter…

sql 插入text字段包含特殊字符_Kettle(PDI)转换中输出之插入/更新详解

概述Insert / update(插入 / 更新)此步骤首先使用一个或多个查询关键字查找表中的一行。如果找不到该行&#xff0c;则插入该行。如果可以找到它&#xff0c;并且要更新的字段相同&#xff0c;则不执行任何操作。如果它们不完全相同&#xff0c;则更新表中的行。注意&#xff1…

一张图让你看清Java集合类(Java集合类的总结)

如今关于Java集合类的文章非常多&#xff0c;可是我近期看到一个非常有意思图片&#xff0c;基本上把Java集合的整体框架都给展现出来了。非常直观。 假设发现图片看不清楚。点此处看大图 在这里&#xff0c;集合类分为了Map和Collection两个大的类别。 处于图片左上角的那一块…

【P1835】小红花

很简单的题&#xff0c;然而我没想到&#xff0c;在NOIP上怎么办嘛QAQ 话说这题不知道怎么分类啊……先扔到玄学里边把…… 原题&#xff1a; Fj在圣诞节来临之际&#xff0c;决定给他的奶牛发一些小红花。现在Fj一共有N头奶牛&#xff0c;这N头牛按照编号1..N&#xff0c;排成…

Cocos2d-x 3.2 Lua演示样例FontTest(字体測试)

Cocos2d-x 3.2 Lua演示样例FontTest&#xff08;字体測试&#xff09;本篇博客介绍Cocos2d-x 3.2中Lua測试项目中的FontTest样例&#xff0c;主要使用了字体文件来创建我们想要的字体样式&#xff1a;第一个參数为文本。第二參数为ttf字体文件&#xff0c;第三个參数为字体大小…

linux上安装memcached步骤

libevent: http://libevent.org/ 服务器端&#xff1a;https://code.google.com/archive/p/memcached/downloads 客户端&#xff1a; http://pecl.php.net/package/memcache 和 http://pecl.php.net/package/memcached 二选一 http://chenzhou123520.iteye.com/blog/1…

具有GlassFish和一致性的高性能JPA –第2部分

在我的四部分系列的第二部分中&#xff0c;我将解释将Coherence与EclipseLink和GlassFish一起使用的策略第一。这描述了配置Coherence的JPA支持的Cache所必须采取的步骤&#xff0c;以及如何在GlassFish中使用它。高性能数据存储。 一般的做法 您可以将Coherence API与通过JPA映…

arm板telnetd为什么运行不了_一种基于ARM的嵌入式系统开发的方案详细讲解

背景介绍在日益信息化的社会中&#xff0c;各种各样的嵌入式系统已经全面渗透到日常生活的每一个角落。嵌入式系统的功能越来越复杂&#xff0c;这就使得一个嵌入式系统产品从市场需求立项到方案选择、样机研制、定型量产所需要的开发费用越来越多&#xff0c;所需开发时间越来…

反素数 -- 数学

反素数就是区间内约数个数最多的那个数。 在ACM题目里&#xff0c; 一般是求约数最多而且数字最小的那个数&#xff0c;【1--n】 二是求约数刚好等于n的最小的那个数 三是求区间里的最小反素数【beign&#xff0c;end】 1和3有区别吗&#xff1f;有&#xff0c;1可以加速&#…

上传文件---未能找到路径“D:\MyProject\Files\”的一部分

C# 使用控件FileUpload 上传文件&#xff0c;简单实例&#xff1a; protected void btnUpload_Click(object sender, EventArgs e){string path Server.MapPath("~/Files/");if (fileUpload.HasFile true){string filename fileUpload.FileName.ToLower();fileUpl…

关于string转整数

又是leetcode的easy级别题&#xff0c;很基本的题目&#xff0c;却漏考虑很多情况&#xff0c;动手前一定要考虑清楚呀&#xff01;&#xff01;&#xff01; 就当做锻炼写作能力吧&#xff0c;先上题目&#xff01; 将文本转换成整数&#xff0c;注意一下几点&#xff1a; 1.文…

数字三角形——递归、递推、记忆化搜索

数字三角形 描述: 有一个由非负整数组成的三角形&#xff0c;第一行只有一个数&#xff0c;除了最下行之外每个数的左下方和右下方各有一个数。 问题&#xff1a; 从第一行的数开始&#xff0c;每次可以往左下或右下走一格&#xff0c;直到走到最下行…

水晶报表分组分栏_web报表可视化设计器工具推荐

古往今来&#xff0c;信息就是决胜的关键。在科技时代的今天亦是如此。企业的数据管理在帮助企业加强管控、提高竞争力等方面具有不可或缺的作用。这就不得不说到报表工具。企业想要将储存于各种商业信息系统中的数据转化成有用的信息&#xff0c;最终帮助决策者做出更快、更好…

Twisted

Twisted定义Twisted是一个基于事件驱动的网络引擎框架网络框架&#xff0c;别人预先定义好的一个框架&#xff08;一个项目&#xff09;&#xff0c;如.net某个web框架有25个class&#xff0c;从BeginRequest依次执行类里的process方法&#xff0c;程序员自己定义一个类&#x…

Centos 6.5 搭建php环境(nginx+mariadb+php7)

1.mariaDb vim /etc/yum.repos.d/MariaDB.repo [mariadb] name MariaDB baseurl http://yum.mariadb.org/5.5/centos5-x86 gpgkeyhttps://yum.mariadb.org/RPM-GPG-KEY-MariaDB gpgcheck1#如果服务器已经安装了MariaDB-Galera-server包&#xff0c;你可能需要在安装MariaDB-s…

读取nas_NAS怎么玩?除了存放小姐姐,它竟然还有这些功能

自从有了电脑&#xff0c;就一直在折腾"存储那点事儿"&#xff0c;说到底&#xff0c;电脑的本质就是存储&#xff0c;而自己弄家用存储方面的东西算下来也有几年了。单机的硬盘存储比较简单&#xff0c;但是随着家里各种设备的增多&#xff0c;各个设备间的文件共享…

OC第一讲:类和对象

今天终于开始进行OC的学习了 一.首先讲了NSLog NSLog是oc里面的输出语句&#xff0c;其用法和printf差不多&#xff0c;但是还是有差别的 1&#xff0c;NSLog是自动换行的&#xff0c;不用像printf那样还需要加\n&#xff1b; 2&#xff0c;NSLog在引号面前需要添加符号&#x…

PL/SQL Developer跑在Oracle 64位数据库上初始化错误

安装完Oracle(64位)、PL/SQL Developer后运行PL/SQL出现如下的错误&#xff1a; 网上查资料说&#xff0c;我的PL/SQL Developer与ORACLE不兼容&#xff0c;即PL/SQL不支持64位的ORACLE&#xff0c;因此得下一个32位的ORCALE客户端并配置相应的参数&#xff1a; 解决步骤小记&a…