C++ 跳转指针算法2025年2月11日 | 阅读 12 分钟 跳跃指针算法是一种旨在优化树结构中祖先查询的高级方法。该算法提高了查找两个节点的最低公共祖先 (LCA) 等操作的效率。通过预处理树,它为每个节点分配一组“跳跃指针”,这些指针是对其特定距离祖先的引用。此预处理步骤涉及以允许快速遍历和查询响应的方式计算和存储这些指针。 方法 1:简单方法实施输出 LCA of nodes 7 and 8 is: 3 LCA of nodes 4 and 5 is: 0 LCA of nodes 6 and 8 is: 0 说明树表示
初始化 初始化了几个数据结构
添加边
预处理 对树进行预处理以计算节点的跳跃指针和深度。这是通过从根开始的深度优先搜索 (DFS) 完成的。 在 DFS 期间
最低公共祖先 (LCA) 查询 查找两个节点 u 和 v 的 LCA
输出
复杂度分析时间复杂度 预处理:预处理步骤涉及深度优先搜索 (DFS) 以计算每个节点的深度并设置跳跃指针。
查询:每个 LCA 查询都涉及调整两个节点的深度并使用跳跃指针查找公共祖先。
空间复杂度 树的存储:邻接列表需要 O(n) 空间,其中 n 是树中节点的数量。 深度数组:存储每个节点的深度需要 O(n) 空间。 跳跃指针:跳跃指针数组需要 O(n log n) 空间。每个节点最多有 O(log n) 个指针,导致总存储需求为 n * log n。 方法二:自底向上方法跳跃指针算法用于高效地查找树中两个节点的最低公共祖先 (LCA)。自底向上方法从叶子开始构建跳跃指针,并向根移动。此方法预处理树以实现快速 LCA 查询。 实施输出 LCA of nodes 7 and 8 is: -1 LCA of nodes 4 and 5 is: -1 LCA of nodes 6 and 8 is: -1 自底向上方法的解释树表示
初始化 初始化了几个数据结构
添加边
预处理(自底向上 DFS) 预处理步骤涉及从根开始的深度优先搜索 (DFS)
查找 LCA 查找两个节点的 LCA
复杂度分析时间复杂度 预处理 深度计算:DFS 对整个树运行一次,每个节点只访问一次。这需要 O(n) 时间,其中 n 是树中节点的数量。 跳跃指针初始化:对于每个节点,我们计算最多 log(n) 个跳跃指针。由于有 n 个节点,因此这部分需要 O(n log n) 时间。 因此,预处理的总时间复杂度为 O(n log n)。 查询 均衡深度:为了使两个节点达到相同的深度,我们可能需要使用跳跃指针最多 log(n) 次。这需要 O(log n) 时间。 同时攀爬:在均衡深度后查找 LCA,我们使用跳跃指针最多 log(n) 次将两个节点向上移动,直到它们的父节点相同。这也需要 O(log n) 时间。 因此,每个查询的时间复杂度为 O(log n)。 空间复杂度 邻接列表:树的邻接列表表示需要 O(n) 空间。 深度数组:存储每个节点的深度需要 O(n) 空间。 跳跃指针:跳跃指针数组是一个 n 行 log(n) 列的二维数组,因此总空间需求为 O(n log n)。 方法三:稀疏表方法稀疏表方法是一种用于预处理树结构以高效查找两个节点的最低公共祖先 (LCA) 的方法。它构建一个稀疏表(二维数组),其中每个条目 st[i][j] 表示节点 i 的第 2^j 个祖先。 实施输出 LCA of nodes 7 and 8 is: 3 LCA of nodes 4 and 5 is: 0 LCA of nodes 6 and 8 is: 0 稀疏表方法的解释树表示 树使用邻接列表 (adj) 表示。每个节点指向其直接子节点。 初始化 初始化了几个数据结构
添加边
预处理(深度计算)
构建稀疏表
查询 LCA 均衡深度:查找两个节点 u 和 v 的 LCA
使用稀疏表:从 2 的最高幂向下到 0
复杂度分析时间复杂度 预处理 深度计算:深度优先搜索 (DFS) 对整个树运行一次,每个节点只访问一次。这需要 O(n) 时间,其中 n 是树中节点的数量。 稀疏表构建:构建稀疏表涉及填充一个大小为 n x log(n) 的二维数组,其中每个单元格都使用前几层的结果进行计算。这也需要 O(n log n) 时间。 因此,预处理的总时间复杂度为 O(n log n)。 查询 均衡深度:使用跳跃指针调整两个节点的深度以使其相同需要 O(log n) 时间。 查找 LCA:在均衡深度后使用稀疏表查找 LCA 也需要 O(log n) 时间。 因此,每个 LCA 查询的时间复杂度为 O(log n)。 空间复杂度 邻接列表:树的邻接列表表示需要 O(n) 空间。 深度数组:存储每个节点的深度需要 O(n) 空间。 稀疏表:稀疏表是一个大小为 n x log(n) 的二维数组,需要 O(n log n) 空间。 下一个主题DART 和 C++ 之间的区别 |
C++ 中的 Lambda 函数提供了一种简洁的方式来定义微小的私有函数。默认情况下,来自其周围作用域的变量可以通过值或引用被 lambda 函数捕获。但是,如果没有 mutable 关键字,捕获的变量就不能被更改。Lambda...
阅读 4 分钟
众所周知的布尔可满足性(SAT)问题在计算机科学、人工智能和逻辑编程中有许多应用,其中有一个有趣的问题实例,称为 2-SAT 问题,或 2-可满足性问题。SAT 问题的主要目标是确定一个给定的布尔公式是否可以...
11 分钟阅读
在本文中,我们将讨论。 deducing_this 功能在 C++ 中是一个高级概念,在 C++20 中引入。它允许更灵活、更清晰的代码,尤其是在考虑 lambda 函数和成员方法时。下面是 deducing_this 的一些功能,涵盖了……
5 分钟阅读
在本文中,我们将讨论其工作原理、伪代码和示例。什么是?1964 年,Stanislaw Ulam 设计了一系列数字,今天被称为 Ulam 数。此数学序列的两个初始正整数表示为 U1 和...
阅读 6 分钟
在本文中,我们将讨论如何在 C++ 中生成随机双精度数。在 C++ 中,头文件提供了许多随机数生成函数,可用于生成随机双精度数。std::random_device 类,它充当种子生成器,以及 std::mt19937 类,它是...(省略)
阅读 4 分钟
在 C++ 编程领域,当涉及到混洗容器中的元素时,开发人员经常会在两个强大的竞争者之间纠结:shuffle 和 random_shuffle。乍一看,这两个函数可能似乎可以互换使用;然而,仔细检查通常会揭示出它们的特性差异...
阅读 6 分钟
4 Sum(查找最接近总和的四元组)问题属于 k-Sum 问题类别,它们都与查找一组总和等于目标或接近目标的数字相关。在这里,问题是确定四个...
阅读 16 分钟
在本文中,我们将讨论如何在 C++ 中查找二维数组中数字的方差。在讨论其实现之前,我们必须了解 C++ 中的二维数组及其语法和示例。什么是二维数组? 在 C++ 中,最基础的类型...
阅读 4 分钟
在本文中,我们将讨论 Pack Indexing 及其用途、优点、缺点和实现。Pack Indexing 指的是一种数据排序方法,以便能够快速获取和操作数据。它是非常重要的一个因素,当...
阅读 6 分钟
在本文中,我们将讨论计算及其需求和示例。乒乓球游戏:在创建 C++ 中的乒乓球游戏时,通常使用 SFML 或 SDL 等图形库来处理渲染、用户输入和游戏机制。游戏……
阅读 6 分钟
我们请求您订阅我们的新闻通讯以获取最新更新。
我们提供所有技术(如 Java 教程、Android、Java 框架)的教程和面试问题
G-13, 2nd Floor, Sec-3, Noida, UP, 201301, India