LeetCode题练习与总结:N皇后

一、题目描述

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

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 条件语句来控制递归过程和决策。

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Matlab将日尺度数据转化为月尺度数据

日尺度转化为月尺度 clcclear all% load datadata xlread(data.xlsx) % 例如该数据为1961-01-01至2022-12-31&#xff0c;共计22645天data data(:,1:3) % 该数据有22645行&#xff0c;数据分别为降水&#xff0c;气温&#xff0c;湿度等三列dt datetime(1961-01-01):datatim…

政安晨:【Keras机器学习实践要点】(十)—— 自定义保存和序列化

目录 导言 涵盖的API Setup 状态保存自定义 构建和编译保存自定义 结论 政安晨的个人主页&#xff1a;政安晨 欢迎 &#x1f44d;点赞✍评论⭐收藏 收录专栏: TensorFlow与Keras机器学习实战 希望政安晨的博客能够对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在…

线程的安全问题

目录 导言&#xff1a; 正文&#xff1a; 1.共享资源&#xff1a; 2.非原子操作&#xff1a; 3.执行顺序不确定&#xff1a; 4.可见性&#xff1a; 5.死锁和饥饿&#xff1a; 6.指令重排序&#xff1a; 总结&#xff1a; 导言&#xff1a; 线程安全是并发编程中的一个…

文献阅读:使用 CellChat 推理和分析细胞-细胞通信

文献介绍 「文献题目」 Inference and analysis of cell-cell communication using CellChat 「研究团队」 聂青&#xff08;加利福尼亚大学欧文分校&#xff09; 「发表时间」 2021-02-17 「发表期刊」 Nature Communications 「影响因子」 16.6 「DOI」 10.1038/s41467-0…

Vue3 使用 v-bind 动态绑定 CSS 样式

在 Vue3 中&#xff0c;可以通过 v-bind 动态绑定 CSS 样式。 语法格式&#xff1a; color: v-bind(数据); 基础使用&#xff1a; <template><h3 class"title">我是父组件</h3><button click"state !state">按钮</button>…

解析CUDA FATBIN格式

参考文档&#xff1a; https://pdfs.semanticscholar.org/5096/25785304410039297b741ad2007e7ce0636b.pdf CUDA Pro Tip: Understand Fat Binaries and JIT Caching | NVIDIA Technical Blog cuda二进制文件中到底有什么 - 知乎 NVIDIA CUDA Compiler Driver NVIDIA CUDA…

HSP_04章_扩展: 进制、位运算

文章目录 10. 扩展: 进制11. 位运算11.1 二进制在运算中的说明11.2 原码 反码 补码11.3位运算符11.3.1 ~按位取反11.3.2 &按位与11.3.3 ^按位异或11.3.4 |按位或11.3.5 << 左移11.3.6 >> 右移 10. 扩展: 进制 进制介绍 进制的转换 2.1 其他进制转十进制 二进…

(八)目标跟踪中参数估计(似然、贝叶斯估计)理论知识

目录 前言 一、统计学基础知识 &#xff08;一&#xff09;随机变量 &#xff08;二&#xff09;全概率公式 &#xff08;三&#xff09;高斯分布及其性质 二、似然是什么&#xff1f; &#xff08;一&#xff09;概率和似然 &#xff08;二&#xff09;极大似然估计 …

国内顶级大牛整理:分布式消息中间件实践笔记+分布式核心原理解析

XMPP JMS RabbitMQ 简介 工程实例 Java 访问RabbitMQ实例 Spring 整合RabbitMQ 基于RabbitMQ的异步处理 基于RabbitMQ的消息推送 RabbitMQ实践建议 虚拟主机 消息保存 消息确认模式 消费者应答 流控机制 通道 总结 ActiveMQ 简介 工程实例 Java 访问ActiveMQ实例…

机器人寻路算法双向A*(Bidirectional A*)算法的实现C++、Python、Matlab语言

机器人寻路算法双向A*&#xff08;Bidirectional A*&#xff09;算法的实现C、Python、Matlab语言 最近好久没更新&#xff0c;在搞华为的软件挑战赛&#xff08;软挑&#xff09;&#xff0c;好卷只能说。去年还能混进32强&#xff0c;今年就比较迷糊了&#xff0c;这东西对我…

EasyRecovery2024汉化精简版,无需注册

EasyRecovery2024是世界著名数据恢复公司 Ontrack 的技术杰作&#xff0c;它是一个威力非常强大的硬盘数据恢复软件。能够帮你恢复丢失的数据以及重建文件系统。 EasyRecovery不会向你的原始驱动器写入任何东东&#xff0c;它主要是在内存中重建文件分区表使数据能够安全地传输…

FL Studio21.2.3中文版软件新功能介绍及下载安装步骤教程

FL Studio21.2中文版的适用人群非常广泛&#xff0c;主要包括以下几类&#xff1a; FL Studio 21 Win-安装包下载如下: https://wm.makeding.com/iclk/?zoneid55981 FL Studio 21 Mac-安装包下载如下: https://wm.makeding.com/iclk/?zoneid55982 音乐制作人&#xff1a…

C#/BS手麻系统源码 手术麻醉管理系统源码 商业项目源码

C#/BS手麻系统源码 手术麻醉管理系统源码 商业项目源码 手麻系统从麻醉医生实际工作环境和流程需求方面设计&#xff0c;与HIS&#xff0c;LIS&#xff0c;PACS&#xff0c;EMR无缝连接&#xff0c;方便查看患者的信息;实现术前、术中、术后手术麻醉信息全记录;减少麻醉医师在…

Spring Boot配置⽂件的格式

1、Spring Boot 配置⽂件有以下三种&#xff1a; &#xff08;1&#xff09;application.properties &#xff08;2&#xff09;application.yml &#xff08;3&#xff09;application.yaml 2、yml 为yaml的简写, 实际开发中出现频率最⾼. yaml 和yml 的使⽤⽅式⼀样 3、 4…

Vue + .NetCore前后端分离,不一样的快速发开框架

摘要&#xff1a; 随着前端技术的快速发展&#xff0c;Vue.NetCore框架已成为前后端分离开发中的热门选择。本文将深入探讨Vue.NetCore前后端分离的快速开发框架&#xff0c;以及它如何助力开发人员提高效率、降低开发复杂度。文章将从基础功能、核心优势、适用范围、依赖环境等…

软考之零碎片段记录(一)

2023上半年选择题 一、流水线周期 注&#xff1a;&#xff08;n-1) * 流水线周期 &#xff08;取址时间分析时间执行时间&#xff09; 注&#xff1a;流水线周期&#xff1a;指令中最耗时的部分&#xff08;取址或者分析或者执行&#xff09; # 耗时最高的部分 * &#xff0…

单例设计模式(3)

单例模式&#xff08;3&#xff09; 实现集群环境下的分布式单例类 如何理解单例模式中的唯一性&#xff1f; 单例模式创建的对象是进程唯一的。以springboot应用程序为例&#xff0c;他是一个进程&#xff0c;可能包含多个线程&#xff0c;单例代表在这个进程的某个类是唯一…

Unity 基于Rigidbody2D模块的角色移动

制作好站立和移动的动画后 控制器设计 站立 移动 角色移动代码如下&#xff1a; using System.Collections; using System.Collections.Generic; using Unity.VisualScripting; using UnityEngine;public class p1_c : MonoBehaviour {// 获取动画组件private Animator …

LeetCode Python - 84. 柱状图中最大的矩形

目录 题目描述解法方法一方法二 运行结果方法一方法二 题目描述 给定 n 个非负整数&#xff0c;用来表示柱状图中各个柱子的高度。每个柱子彼此相邻&#xff0c;且宽度为 1 。 求在该柱状图中&#xff0c;能够勾勒出来的矩形的最大面积。 示例 1: 输入&#xff1a;heights …

《最小阻力之路》利用最小阻力路径,采用创造性思维模式,更有效地实现个人愿景和目标 - 三余书屋 3ysw.net

最小阻力之路 大家好&#xff0c;今天我们分享《最小阻力之路》。我们时常听到有人感叹&#xff0c;明明懂得那么多道理&#xff0c;为何生活过得不如意呢&#xff1f;这本书从某种角度回应了这个疑问&#xff0c;作者分析了我们在人生旅途中屡次失败的原因&#xff0c;提出了…