LeetCode题练习与总结:N皇后

news2024/11/26 23:25:57

一、题目描述

按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。

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

二、解题思路

  1. 初始化一个 n x n 的棋盘,每个位置初始为 '.'。
  2. 使用递归回溯的方法尝试在每一行放置一个皇后。
  3. 在尝试放置皇后时,检查是否有冲突(即该位置是否在之前放置的皇后的攻击范围内,包括同一行、同一列以及两个对角线)。
  4. 如果在某一行找不到合适的位置放置皇后,则回溯到上一行。
  5. 当所有行都成功放置了皇后后,记录当前棋盘的状态为一个解。
  6. 继续递归搜索,直到找到所有可能的解。

三、具体代码

import java.util.ArrayList;
import java.util.List;

class Solution {
    public List<List<String>> solveNQueens(int n) {
        List<List<String>> solutions = new ArrayList<>();
        List<Integer> columns = new ArrayList<>(); // 用于记录每行皇后的列位置
        char[][] board = new char[n][n];
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                board[i][j] = '.';
            }
        }
        backtrack(board, solutions, columns, 0);
        return solutions;
    }

    private void backtrack(char[][] board, List<List<String>> solutions, List<Integer> columns, int row) {
        if (row == board.length) {
            // A solution is found, add it to the solutions list
            solutions.add(convertBoardToStringList(board));
            return;
        }
        for (int col = 0; col < board.length; col++) {
            if (isValid(board, columns, row, col)) {
                columns.add(col); // 将当前皇后的列位置添加到列表中
                board[row][col] = 'Q'; // 放置皇后
                backtrack(board, solutions, columns, row + 1); // 递归放置下一行的皇后
                columns.remove(columns.size() - 1); // 回溯,移除当前皇后的列位置
                board[row][col] = '.'; // 移除皇后,回溯
            }
        }
    }

    private boolean isValid(char[][] board, List<Integer> columns, int row, int col) {
        // Check if the current position is under attack
        for (int i = 0; i < row; i++) {
            if (board[i][col] == 'Q' || columns.contains(col)) {
                return false; // 同一列或同行已有皇后
            }
            // Check upper diagonal
            int diag1 = col - (row - i);
            if (diag1 >= 0 && board[i][diag1] == 'Q') {
                return false;
            }
            // Check lower diagonal
            int diag2 = col + (row - i);
            if (diag2 < board.length && board[i][diag2] == 'Q') {
                return false;
            }
        }
        return true;
    }

    private List<String> convertBoardToStringList(char[][] board) {
        List<String> boardStr = new ArrayList<>();
        for (int i = 0; i < board.length; i++) {
            StringBuilder sb = new StringBuilder();
            for (int j = 0; j < board[i].length; j++) {
                sb.append(board[i][j]);
            }
            boardStr.add(sb.toString());
        }
        return boardStr;
    }
}

四、时间复杂度和空间复杂度

1. 时间复杂度
  • 回溯算法的时间复杂度通常较难直接计算,因为它依赖于问题的解空间结构。在 n 皇后问题中,我们需要在 n 行中每行放置一个皇后,且皇后之间不能相互攻击。
  • 对于每一行,我们有 n 个可能的位置来放置皇后。因此,如果我们不考虑冲突检查,最坏情况下的尝试次数是 n^n。
  • 然而,由于皇后不能攻击同一行、同一列或对角线上的其他皇后,实际尝试次数会少得多。每次递归调用都会减少一个可行的选择,因此时间复杂度大致为 O(n!),因为每一步都需要检查当前位置是否安全,这需要 O(n) 的时间。
  • 但是,由于我们在每一行放置皇后时都会剪枝(即跳过不符合条件的位置),实际的时间复杂度通常要好于 O(n!)。具体的时间复杂度取决于剪枝的效率。
2. 空间复杂度
  • 空间复杂度主要由棋盘的大小和递归栈的深度决定。
  • 棋盘是一个 n x n 的二维数组,因此空间复杂度为 O(n^2)。
  • 递归栈的深度最坏情况下可以达到 n,因为我们需要递归 n 次来放置 n 个皇后。此外,我们在递归过程中使用了一个 columns 列表来存储每行皇后的列位置,这个列表的长度最多为 n。
  • 因此,总的空间复杂度为 O(n^2 + n),其中 n^2 是棋盘的空间占用,n 是递归栈和 columns 列表的空间占用。通常,我们关注最坏情况下的空间复杂度,所以可以表示为 O(n^2)。

请注意,尽管这个算法的时间复杂度可能看起来很高,但实际上由于有效的剪枝,它通常能够在合理的时间内找到所有解。

五、总结知识点

1. 回溯算法(Backtracking):

  • 回溯算法是一种通过递归来试探和回溯的算法,它尝试分步解决一个问题。
  • 在 n 皇后问题中,回溯算法用于逐行放置皇后,并在每一步中检查是否满足条件。
  • 当找到一个解时,算法会记录下来,然后继续寻找其他可能的解。

2. 位运算(Bitwise Operations):

  • 代码中没有直接使用位运算,但位运算常用于优化回溯算法中的冲突检查,例如使用位掩码来跟踪列和对角线上的皇后位置。

3. 递归(Recursion):

  • 递归是回溯算法的核心,它允许函数调用自身来解决问题的一部分。
  • 在这段代码中,backtrack 方法是一个递归函数,它在每一行尝试放置一个皇后,并在成功放置后递归调用自身来放置下一行的皇后。

4. 数据结构:

  • ArrayList 用于存储解决方案和列位置。
  • char[][] 用于表示棋盘,其中每个字符表示棋盘上的一个位置('Q' 表示皇后,'.' 表示空位)。

5. 条件检查(Condition Checking):

  • isValid 方法用于检查当前位置是否可以放置皇后,它检查了同一行、同一列和两个对角线上是否有其他皇后。

6. 字符串操作(String Manipulation):

  • convertBoardToStringList 方法将二维字符数组转换为字符串列表,以便输出解决方案。

7. List 操作:

  • 使用 Listaddremove 方法来管理列位置的列表。

8. 控制流(Control Flow):

  • 使用 for 循环和 if 条件语句来控制递归过程和决策。

以上就是解决这个问题的详细步骤,希望能够为各位提供启发和帮助。

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

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

相关文章

【嵌入式——C语言】VScode编写C程序、交叉编译

【嵌入式——C语言】VScode编写C程序、交叉编译 第一步第二步第三步第四步第五步第六步第七步第八步 第一步 下载Visual Studio Code下载地址 然后直接安装就可以了。 第二步 前提是你的电脑上安装了WSL。。。 打开vscode的扩展&#xff0c;输入WSL进行安装 安装完之后在窗…

SpringBoot 集成分布式任务调度 XXL-JOB【保姆级上手】

文章目录 XXL-JOB 介绍分布式任务调度XXL-JOB 概述 快速入门下载源码初始化调度数据库编译源码调度中心调度中心介绍配置调度中心部署调度中心集群部署调度中心&#xff08;可选&#xff09;Docker 镜像方式搭建调度中心&#xff08;可选&#xff09; 执行器执行器介绍添加依赖…

DOM 节点遍历:掌握遍历 XML文档结构和内容的技巧

遍历是指通过或遍历节点树 遍历节点树 通常&#xff0c;您想要循环一个 XML 文档&#xff0c;例如&#xff1a;当您想要提取每个元素的值时。 这被称为"遍历节点树"。 下面的示例循环遍历所有 <book> 的子节点&#xff0c;并显示它们的名称和值&#xff1a;…

交替子数组计数 - 力扣题解

⭐简单说两句⭐ ✨ 正在努力的小新~ &#x1f496; 超级爱分享&#xff0c;分享各种有趣干货&#xff01; &#x1f469;‍&#x1f4bb; 提供&#xff1a;模拟面试 | 简历诊断 | 独家简历模板 &#x1f308; 感谢关注&#xff0c;关注了你就是我的超级粉丝啦&#xff01; &…

设计模式(一)简介

一、书籍推荐及博客 大话设计模式 设计模式的艺术 XXL开源社区 | 博客 二、通俗版概念 创建型模式、结构型模式、行为型模式 怎么建房子、建什么样的房子、建的房子有什么用 三、重点模式及简述 1、创建型模式 工厂方法&#xff08;多态工厂的实现&#xff09; 抽象工厂…

JAVA流 学习思考

1. 水在前面 接着上周的Lambda表达式&#xff0c;这周学习了流。说实话作为工具来讲&#xff0c;这玩意好像挺强大的&#xff0c;倒是真要掌握这工具貌似要记住不少东西&#xff0c;年纪大了不想背书的可以看看这篇水文&#xff0c;等到用的时候再根据具体的使用找度娘。&#…

常用技术-Timer定时器

什么是Timer Timer是JDK自带的任务调度工具类&#xff0c;只需要java.util.Timer和java.util.TimerTask两个类就可以实现基本任务调度功能 Timer是一种线程设施&#xff0c;用于安排以后在后台线程中执行的任务。可安排任务执行一次&#xff0c;或者定期重复执行&#xff0c;…

谈谈配置中心?

配置中心可以做集中式的服务配置管理&#xff0c;比如配置一些数据库连接的URL&#xff0c;一些共用的配置且可动态调整的参数。如果不采用集中式的管理&#xff0c;会导致修改起来特别麻烦&#xff0c;一个个的修改特别繁琐。 Nacos Config配置中心中采用的是客户端拉取数据&a…

腾讯云轻量应用服务器“月流量”限制?流量不够怎么办?

腾讯云轻量应用服务器套餐带流量包&#xff0c;就是有月流量限制的意思&#xff0c;超出轻量套餐的流量需要另外支付流量费&#xff0c;轻量服务器地域不同超额流量费用也不同&#xff0c;北京上海广州等中国内地地域流量价格是0.8元每GB&#xff0c;中国香港地域流量价格是1元…

Xilinx IDDR及ODDR使用和仿真

平台&#xff1a;Vivado2018 官方相关文档&#xff0c;ug471_7Series_SelectIO.pdf 关于IDDR与ODDR Input DDR Resource(IDDR) 外部的数据在时钟的上下沿同时传输数据&#xff0c;我们可以使用IDDR原语将输入的单bit数据转化为2bit的数据输出。同时数据速率变为原来的二分之一…

python的Web框架比较

个人博客:Sekyoro的博客小屋 个人网站:Proanimer的个人网站 之前好像写过一些关于Python的Web框架?现在再按照ASGI与原本的WSGI区分一下,顺便把框架(framework)与库(library)区分一下. 之前我也写过(或者说想过)一些类似生态以及作用的框架进行比较,大多都是看看网上评价以及s…

微服务demo(三)nacosfeign

一、feign使用 1、集成方法 1.1、pom consumer添加依赖 <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId><version>2.2.6.RELEASE</version></dependency&…

算法学习——LeetCode力扣补充篇2

算法学习——LeetCode力扣补充篇2 724. 寻找数组的中心下标 724. 寻找数组的中心下标 - 力扣&#xff08;LeetCode&#xff09; 描述 给你一个整数数组 nums &#xff0c;请计算数组的 中心下标 。 数组 中心下标 是数组的一个下标&#xff0c;其左侧所有元素相加的和等于右…

C语言 05 变量与常量

变量 变量就像在数学中学习的 x&#xff0c;y 一样&#xff0c;可以直接声明一个变量&#xff0c;并利用这些变量进行基本的运算&#xff0c;声明变量的格式为&#xff1a; 数据类型 变量名称 初始值;&#xff08;其中初始值可以不用在定义变量时设定&#xff09; 是赋值操作…

【python】常用函数汇总(持续更新……)

文章目录 【numpy.exp()】返回e的幂次方&#xff0c;e是一个常数为2.71828【np.dot()】矩阵相乘【np.linalg.inv()】矩阵求逆 【numpy.exp()】返回e的幂次方&#xff0c;e是一个常数为2.71828 举例&#xff1a;numpy.exp() 【np.dot()】矩阵相乘 【要点】 1、前者的列数后者…

Springboot之RESTful风格

目录 1、概述&#xff1a; 1.1、传统风格的API&#xff1a; 1.2、RESTful风格的API&#xff1a; 1.3、GET、POST、PUT、DELETE&#xff1a; 2、RESTful风格相关的注解&#xff1a; ①PathVariable&#xff0c;用来获取url中的数据&#xff1b; ②GetMapping&#xff0c;接…

Xcode删除原本的Git,再添加新的git

本文参考&#xff1a;Xcode怎么删除原本git,在重新设置新的git地址_ios xcode 删除原本git-CSDN博客 开发中会有一个问题。Xcode项目A 提交到Git服务器server1&#xff0c;此时项目A内部已经存在一个Git文件&#xff0c;与server1相关联。 此时你想将项目A提交到 另一个Git…

SSH免密登录——linux

SSH免密登录——linux 方法一一、用 ssh-key-gen 在本地主机上创建公钥和密钥二、用 ssh-copy-id 把客户端公钥追加到远程主机的 .ssh/authorized_key 上三、直接登录远程主机 方法二一、将生成的客户端公钥id_rsa.pub内容追加至目标主机.ssh/authorized_key 中参考链接 SSH免密…

论文阅读,Accelerating the Lattice Boltzmann Method(五)

目录 一、Article:文献出处&#xff08;方便再次搜索&#xff09; &#xff08;1&#xff09;作者 &#xff08;2&#xff09;文献题目 &#xff08;3&#xff09;文献时间 &#xff08;4&#xff09;引用 二、Data:文献数据&#xff08;总结归纳&#xff0c;方便理解&am…

【vue2+antvx6】报错Cannot read properties of undefined (reading ‘toUpperCase‘)

我的代码是这样的 <el-collapseref"collapse"v-model"active"accordionclass"collapseStart"change"collapsechange"><el-collapse-item:name"String(index 1)"v-for"(i, index) in List":key"in…