LeetCode【0051】N皇后

本文目录

  • [1 中文题目](#1 中文题目)
  • [2 求解方法:回溯法](#2 求解方法:回溯法)
    • [2.1 方法思路](#2.1 方法思路)
    • [2.2 Python代码](#2.2 Python代码)
    • [2.3 复杂度分析](#2.3 复杂度分析)
  • [3 题目总结](#3 题目总结)

1 中文题目

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

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

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

每一种解法包含一个不同的 n 皇后问题 的棋子放置方案,该方案中 'Q' 和 '.' 分别代表了皇后和空位。

示例:

复制代码
输入:n = 4
输出:[[".Q..","...Q","Q...","..Q."],
      ["..Q.","Q...","...Q",".Q.."]]
解释:如上图所示,4 皇后问题存在两个不同的解法。

输入:n = 1
输出:[["Q"]]

提示:

  • 1 ≤ n ≤ 9 1\leq n \leq 9 1≤n≤9

2 求解方法:回溯法

2.1 方法思路

方法核心

使用回溯法逐行放置皇后,通过三个集合分别记录已被占用的列、主对角线和副对角线,利用主对角线上r-c值相等和副对角线上r+c值相等的特性来快速判断位置是否可用,避免了逐个检查的开销,同时使用回溯来探索所有可能的解。

实现步骤

(1)初始化阶段:

  • 创建结果列表存储所有解法
  • 创建queens列表存储已放置的皇后位置
  • 创建三个集合分别记录被占用的列和对角线

(2)回溯过程:

  • 从第一行开始,逐行放置皇后
  • 对每一行,尝试在每一列放置皇后
  • 检查当前位置是否满足条件
  • 放置皇后并更新三个集合的信息
  • 递归处理下一行
  • 回溯时移除当前皇后并清理相关信息

(3)位置检查:

  • 检查当前列是否已被占用
  • 检查主对角线(r-c)是否已被占用
  • 检查副对角线(r+c)是否已被占用
  • 所有条件都满足才能放置皇后

(4)生成结果:

  • 当放置了n个皇后时生成棋盘表示
  • 将当前解加入结果列表
  • 继续回溯寻找其他解

方法示例

以 n = 4 的情况为例:

python 复制代码
初始状态:
queens = []
cols = set()
diag1 = set()
diag2 = set()

第一次尝试(从第一行开始):
row = 0, col = 0
放置第一个皇后:
queens = [(0,0)]
cols = {0}
diag1 = {0}
diag2 = {0}
棋盘状态:
Q...
....
....
....

继续到第二行(row=1):
尝试col=2(col=0,1不行因为被攻击)
queens = [(0,0), (1,2)]
cols = {0,2}
diag1 = {0,-1}
diag2 = {0,3}
棋盘状态:
Q...
..Q.
....
....

继续到第三行(row=2):
发现无法放置,回溯到第二行...

经过多次回溯,找到第一个完整解:
最终queens = [(0,1), (1,3), (2,0), (3,2)]
对应棋盘:
.Q..
...Q
Q...
..Q.

继续回溯找其他解...

2.2 Python代码

python 复制代码
class Solution:
    def solveNQueens(self, n: int) -> List[List[str]]:
        # 存储所有解法
        results = []
        # 用于存储已放置的皇后的位置信息
        queens = []
        # 记录列、主对角线、副对角线是否被占用
        cols = set()
        diag1 = set()  # 主对角线 r-c 为常数
        diag2 = set()  # 副对角线 r+c 为常数

        def create_board():
            # 根据皇后位置创建棋盘
            board = []
            for r, c in queens:
                row = '.' * c + 'Q' + '.' * (n-c-1)
                board.append(row)
            return board

        def backtrack(row):
            # 如果已经放置了n个皇后,说明找到一个解
            if row == n:
                results.append(create_board())
                return

            # 尝试在当前行的每一列放置皇后
            for col in range(n):
                # 检查当前位置是否可以放置皇后
                if col not in cols and \
                   row - col not in diag1 and \
                   row + col not in diag2:
                    # 放置皇后,并记录相关信息
                    queens.append((row, col))
                    cols.add(col)
                    diag1.add(row - col)
                    diag2.add(row + col)
                    
                    # 继续处理下一行
                    backtrack(row + 1)
                    
                    # 回溯:移除当前放置的皇后
                    queens.pop()
                    cols.remove(col)
                    diag1.remove(row - col)
                    diag2.remove(row + col)

        backtrack(0)
        return results

2.3 复杂度分析

  • 时间复杂度:O(N!)
    • 第一行有N种选择
    • 第二行最多有N-1种选择
    • 第三行最多有N-2种选择
    • 依此类推
    • 实际运行时间会小于N!,因为许多分支会被提前剪枝
  • 空间复杂度:O(N)
    • queens列表存储N个皇后位置:O(N)
    • 三个集合最多存储N个元素:O(N)
    • 递归调用栈深度为N:O(N)
    • 存储每个解需要O(N)空间

3 题目总结

题目难度:困难
数据结构:数组
应用算法:回溯法

相关推荐
科技林总21 分钟前
解决vllm服务漏扫问题
python·安全
菜鸟‍1 小时前
LeetCode 1 27 和 704 || 两数之和 移除元素 二分查找
算法·leetcode·职场和发展
财经资讯数据_灵砚智能2 小时前
基于全球经济类多源新闻的NLP情感分析与数据可视化(夜间-次晨)2026年6月10日
大数据·人工智能·python·ai·信息可视化·自然语言处理·灵砚智能
namexingyun2 小时前
拆解Fable 5三重安全护栏:模型路由、蒸馏防护与生物安全分类器的技术原理 - 微元算力(weytoken)
java·人工智能·python·安全·架构·ai编程
chenment2 小时前
别再为每个模型单独写一套队列了:用 200 行代码封装多模态统一调用层
人工智能·python·产品
退休倒计时2 小时前
【每日一题】LeetCode 142. 环形链表 II TypeScript
算法·leetcode·链表·typescript
啊森要自信2 小时前
【GUI自动化测试】控件、鼠标键盘操作与多场景自动化
c语言·开发语言·python·adb·ipython
YJlio2 小时前
《Sysinternals实战指南》16.5 Ctrl2Cap 工具详解:把 Caps Lock 变成 Ctrl 的键盘改造与回退方法
linux·运维·服务器·网络·python·学习·计算机外设
某林2122 小时前
从底层硬件死锁到 QoS 通信底层的全链路复盘
python·ros2·qos
Jutick2 小时前
WebSocket 连接没断,行情却停了:如何给实时数据流加双层 watchdog?
python