LeetCode51

news/2025/2/23 6:27:02

LeetCode51

目录

  • 题目描述
  • 示例
  • 思路分析
  • 代码段
  • 代码逐行讲解
  • 复杂度分析
  • 总结的知识点
  • 整合
  • 总结

题目描述

N 皇后问题:将 n 个皇后放置在 n x n 的棋盘上,使得皇后彼此之间不能相互攻击(即任何两个皇后不能在同一行、同一列或同一斜线上)。

返回所有不同的解决方案。每个解决方案包含一个明确的 n x n 的棋盘布局,其中 'Q' 表示皇后,'.' 表示空位。


示例

示例 1

输入:

java">n = 4

输出:

java">[
 [".Q..",  // 解法 1
  "...Q",
  "Q...",
  "..Q."],

 ["..Q.",  // 解法 2
  "Q...",
  "...Q",
  ".Q.."]
]

解释:

  • 4 皇后问题有两个不同的解决方案。

示例 2

输入:

java">n = 1

输出:

java">[["Q"]]

解释:

  • 1 皇后问题只有一个解决方案。

思路分析

问题核心

我们需要在 n x n 的棋盘上放置 n 个皇后,使得它们互不攻击。皇后可以攻击同一行、同一列或同一斜线上的其他皇后。

思路拆解

  1. 回溯算法
    • 使用回溯算法逐行放置皇后,并在每一行中尝试所有可能的列。
  2. 冲突检测
    • 使用三个布尔数组分别记录列、左斜线和右斜线的冲突情况。
    • 列冲突:ca[j] 表示第 j 列是否被占用。
    • 左斜线冲突:cb[i + j] 表示左斜线是否被占用。
    • 右斜线冲突:cc[n - 1 - (i - j)] 表示右斜线是否被占用。
  3. 递归终止条件
    • 如果成功放置了 n 个皇后,则将当前棋盘布局加入结果列表。
  4. 回溯
    • 在递归返回时,撤销当前皇后的放置,并恢复冲突数组的状态。

代码段

java">class Solution {
    public List<List<String>> solveNQueens(int n) {
        List<List<String>> ans = new ArrayList<>();
        boolean[] ca = new boolean[n]; 
        boolean[] cb = new boolean[2 * n - 1]; 
        boolean[] cc = new boolean[2 * n - 1];
        char[][] table = new char[n][n]; 
        for (int i = 0; i < n; i++) {
            Arrays.fill(table[i], '.'); 
        }
        dfs(0, n, table, ca, cb, cc, ans); 
        return ans;
    }

    static void dfs(int i, int n, char[][] table,
            boolean[] ca,
            boolean[] cb,
            boolean[] cc,
            List<List<String>> ans) {
        if (i == n) { 
            List<String> solution = new ArrayList<>();
            for (char[] chars : table) {
                solution.add(new String(chars)); 
            }
            ans.add(solution);
            return;
        }
        for (int j = 0; j < n; j++) { 
            if (ca[j] || cb[i + j] || cc[n - 1 - (i - j)]) {
                continue;
            }
            table[i][j] = 'Q';
            ca[j] = cb[i + j] = cc[n - 1 - (i - j)] = true; 
            dfs(i + 1, n, table, ca, cb, cc, ans); 
            table[i][j] = '.'; 
            ca[j] = cb[i + j] = cc[n - 1 - (i - j)] = false;        }
    }
}

在这里插入图片描述


代码逐行讲解

1. 初始化结果列表

java">List<List<String>> ans = new ArrayList<>();
  • ans 用于存储所有合法的棋盘布局。

2. 初始化冲突数组

java">boolean[] ca = new boolean[n]; // 列冲突
boolean[] cb = new boolean[2 * n - 1]; // 左斜线冲突
boolean[] cc = new boolean[2 * n - 1]; // 右斜线冲突
  • ca 记录每一列是否被占用。
  • cb 记录每一条左斜线是否被占用。
  • cc 记录每一条右斜线是否被占用。

3. 初始化棋盘

java">char[][] table = new char[n][n];
for (int i = 0; i < n; i++) {
    Arrays.fill(table[i], '.'); // 初始化棋盘
}
  • table 表示棋盘,初始化为 '.'

4. 调用 DFS

java">dfs(0, n, table, ca, cb, cc, ans);
  • 从第 0 行开始递归放置皇后。

5. DFS 函数

java">static void dfs(int i, int n, char[][] table,
        boolean[] ca,
        boolean[] cb,
        boolean[] cc,
        List<List<String>> ans) {
  • DFS 函数的定义,用于递归放置皇后。

6. 找到一个解

java">if (i == n) {
    List<String> solution = new ArrayList<>();
    for (char[] chars : table) {
        solution.add(new String(chars));
    }
    ans.add(solution);
    return;
}
  • 如果成功放置了 n 个皇后,则将当前棋盘布局加入结果列表。

7. 尝试放置皇后

java">for (int j = 0; j < n; j++) {
  • 在第 i 行的每一列尝试放置皇后。

8. 冲突检测

java">if (ca[j] || cb[i + j] || cc[n - 1 - (i - j)]) {
    continue;
}
  • 如果当前列、左斜线或右斜线有冲突,则跳过。

9. 放置皇后

java">table[i][j] = 'Q';
ca[j] = cb[i + j] = cc[n - 1 - (i - j)] = true;
  • 放置皇后,并标记冲突。

10. 递归

java">dfs(i + 1, n, table, ca, cb, cc, ans);
  • 递归放置下一行的皇后。

11. 回溯

java">table[i][j] = '.';
ca[j] = cb[i + j] = cc[n - 1 - (i - j)] = false;
  • 回溯时撤销皇后的放置,并恢复冲突数组的状态。

复杂度分析

时间复杂度

  • 最坏情况下需要遍历所有可能的放置方式,时间复杂度为 O(n!)

空间复杂度

  • 需要存储所有合法的棋盘布局,空间复杂度为 O(n^2 * n!)
  • 递归栈的深度为 n,因此额外空间复杂度为 O(n)

总结的知识点

1. 回溯算法

  • 使用回溯算法逐行放置皇后,并在递归返回时撤销操作。

2. 冲突检测

  • 使用布尔数组记录列、左斜线和右斜线的冲突情况。

3. 递归与回溯

  • 通过递归实现深度优先搜索,并通过回溯撤销操作。

4. 棋盘表示

  • 使用二维字符数组表示棋盘,并用 'Q''.' 分别表示皇后和空位。

整合

java">class Solution {
    public List<List<String>> solveNQueens(int n) {
        List<List<String>> ans = new ArrayList<>(); // 结果列表
        boolean[] ca = new boolean[n]; // 列冲突
        boolean[] cb = new boolean[2 * n - 1]; // 左斜线冲突
        boolean[] cc = new boolean[2 * n - 1]; // 右斜线冲突
        char[][] table = new char[n][n]; // 棋盘
        for (int i = 0; i < n; i++) {
            Arrays.fill(table[i], '.'); // 初始化棋盘
        }
        dfs(0, n, table, ca, cb, cc, ans); // DFS
        return ans;
    }

    static void dfs(int i, int n, char[][] table,
            boolean[] ca,
            boolean[] cb,
            boolean[] cc,
            List<List<String>> ans) {
        if (i == n) { // 找到一个解
            List<String> solution = new ArrayList<>();
            for (char[] chars : table) {
                solution.add(new String(chars)); // 将棋盘布局加入解
            }
            ans.add(solution); // 将解加入结果列表
            return;
        }
        for (int j = 0; j < n; j++) { // 尝试在第 i 行的每一列放置皇后
            if (ca[j] || cb[i + j] || cc[n - 1 - (i - j)]) { // 冲突检测
                continue;
            }
            table[i][j] = 'Q'; // 放置皇后
            ca[j] = cb[i + j] = cc[n - 1 - (i - j)] = true; // 标记冲突
            dfs(i + 1, n, table, ca, cb, cc, ans); // 递归
            table[i][j] = '.'; // 回溯
            ca[j] = cb[i + j] = cc[n - 1 - (i - j)] = false; // 撤销冲突标记
        }
    }
}

总结

通过回溯算法和冲突检测,能够高效地解决 N 皇后问题。


http://www.niftyadmin.cn/n/5863114.html

相关文章

Docker教程(喂饭级!)

如果你有跨平台开发的需求&#xff0c;或者对每次在新机器上部署项目感到头疼&#xff0c;那么 Docker 是你的理想选择&#xff01;Docker 通过容器化技术将应用程序与其运行环境隔离&#xff0c;实现快速部署和跨平台支持&#xff0c;极大地简化了开发和部署流程。本文详细介绍…

线代[8]|北大丘维声教授《怎样学习线性代数?》(红色字体为博主注释)

文章目录 说明一、线性代数的内容简介二、学习线性代数的用处三、线性代数的特点四、学习线性代数的方法五、更新时间记录 说明 文章中红色字体为博主敲录完丘教授这篇文章后所加&#xff0c;刷到这篇文章的读者在首次阅读应当跳过红色字体&#xff0c;先通读一读文章全文&…

深度学习之特征提取

前言 深度学习就是把输入转换成一个高维的向量&#xff0c;之后利用这个向量去完成分类、回归等任务。 深度学习特征工程知识图谱 1. 特征提取的本质 核心目标&#xff1a;将原始数据→高维语义特征向量 监督驱动&#xff1a;标签决定特征提取方向 典型架构&#xff1a; …

Javascript排序算法(冒泡排序、快速排序、选择排序、堆排序、插入排序、希尔排序)详解

JS 排序算法详解 排序算法是计算机科学中的基础&#xff0c;用于将一组数据按照某种顺序重新排列。JavaScript中常见的排序算法包括冒泡排序、选择排序、插入排序、快速排序、归并排序等。以下是这些算法的详细介绍和代码示例。 冒泡排序&#xff08;Bubble Sort&#xff09;…

GPIO外设

一、GPIO简介 GPIO&#xff0c;general-purpos IO port,通用输入输出引脚&#xff0c;所有的GPIO引脚都有基本的输入输出功能。 最基本的输出功能&#xff1a;STM32控制引脚输出高、低电平&#xff0c;实现开关控制&#xff1b;最基本的输入功能&#xff1a;检测外部输入电平&…

CDGA|企业数据治理实战:从疏通“信息河”到打造优质“数据湖”

在当今的数字化时代&#xff0c;数据已成为企业的重要资产&#xff0c;其价值不言而喻。然而&#xff0c;面对海量的数据&#xff0c;如何进行有效的治理&#xff0c;将其转化为企业的竞争优势&#xff0c;成为了众多企业面临的难题。本文将深入探讨企业数据治理的实战策略&…

[实现Rpc] 服务端 | RpcRouter实现 | Builder模式

目录 项目服务端独用类的实现 1. RpcRouter类的实现 ServiceDescribe SDescribeFactory ⭕ Builder模式 1. 动机 2. 模式定义 3. 要点总结 4. 代码感受 ServiceManager RpcRouter 4. 代码感受 ServiceManager RpcRouter 前文我们就将 Rpc 通用类都实现完啦&#…

MySQL 架构

目录 1. MySQL 架构概览 (1) 客户端/服务器架构 (2) 存储引擎架构 2. 主要组件 (1) 客户端工具 (2) MySQL 服务器 (3) 存储引擎 3. MySQL 架构图 4. MySQL 架构的特点 5. MySQL 的高级架构 (1) 主从复制&#xff08;Master-Slave Replication&#xff09; (2) 主主…