- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我有一些degenerate tree
(看起来像数组或双向链表)。例如,这棵树:
每个边缘都有一定的重量。我想找到从每个顶点开始的所有相等路径。
换句话说,我想获取所有元组(v1,v,v2),其中v1和v2是任意祖先和后代,即c(v1, v) = c(v, v2)
。
让边缘具有以下权重(仅作为示例):a-b = 3
b-c = 1
c-d = 1
d-e = 1
然后:
A
没有相等的路径(左侧没有顶点)。 B
具有一对相等的对。路径B-A
等于路径B-E
(3 == 3)
。 C
具有一对相等的对。路径B-C
等于路径C-D
(1 == 1)
。 D
具有一对相等的对。路径C-D
等于路径D-E
(1 == 1)
。 E
没有相等的路径(右侧没有顶点)。 O(n^2)
中工作。但这对我来说太慢了。
最佳答案
您在评论中写道,当前的方法是
It seems, I looking for a way to decrease constant in O(n^2). I choose some vertex. Then I create two set. Then I fill these sets with partial sums, while iterating from this vertex to start of tree and to finish of tree. Then I find set intersection and get number of paths from this vertex. Then I repeat algorithm for all other vertices.
O(n^2)
方法。
v
同时进入两个可能的方向。将一个“指针”指向一个在一个方向上移动的顶点(
vl
),将另一个(
vr
)朝另一个方向移动,并尝试使
v
到
vl
的距离尽可能接近
v
到
vr
的距离。每次这些距离相等时,您将拥有相等的路径。
for v in vertices
vl = prev(v)
vr = next(v)
while (vl is still inside the tree)
and (vr is still inside the tree)
if dist(v,vl) < dist(v,vr)
vl = prev(vl)
else if dist(v,vr) < dist(v,vl)
vr = next(vr)
else // dist(v,vr) == dist(v,vl)
ans = ans + 1
vl = prev(vl)
vr = next(vr)
dist
。)
L
,则算法以
O(L log L)
运行。但是,它在概念上要先进得多,编码也要先进得多。
v
。让我们有两个数组,
a
和
b
,不是C样式的零索引数组,而是索引从
-L
到
L
的数组。
i>0
,a[i]=1
iff在v
右边的距离上,恰好是i
是一个顶点,否则为a[i]=0
i=0
,a[i]≡a[0]=1
i<0
,a[i]=1
iff在v
的左侧,距离上-i
正好有一个顶点,否则a[i]=0
v
位于原点。然后
a[i]=1
如果在坐标
i
处有一个顶点。
v
:
a--------b--c--d--e
--|--|--|--|--|--|--|--|--|-->
-4 -3 -2 -1 0 1 2 3 4
a: ... 0 1 0 0 1 1 1 1 0 ...
b
数组,我们相对于原点以对称方式定义值,就好像我们已经反转了轴的方向一样:
i>0
,b[i]=1
iff在v
左侧,恰好距离i
是一个顶点,否则为b[i]=0
i=0
,b[i]≡b[0]=1
i<0
,b[i]=1
iff在v
的右边,距离上-i
恰好有一个顶点,否则b[i]=0
c
,使得
c[i]=a[i]*b[i]
,星号在此处保持普通乘法。显然,
c[i]=1
是在顶点中长度为
abs(i)
到左端的路径,而在顶点中是长度
abs(i)
到右端的路径。因此,对于
i>0
,
c
中具有
c[i]=1
的每个位置都与您所需的路径相对应。还有负数位置(
c[i]=1
和
i<0
),它们仅反射(reflect)正数位置,还有一个位置
c[i]=1
的位置,即
i=0
。
c
中所有元素的总和。该总和为
sum(c)=2P+1
,其中
P
是以
v
为中心的所需路径总数。因此,如果您知道
sum(c)
,就可以轻松确定
P
。
a
和
b
数组,以及当我们更改顶点
v
时它们如何变化。让我们将
v0
表示为最左边的顶点(树的根),并将
a0
和
b0
表示为该顶点的相应
a
和
b
数组。
v
表示
d=dist(v0,v)
。然后很容易看出,对于顶点
v
,数组
a
和
b
只是由
a0
移位的数组
b0
和
d
:
a[i]=a0[i+d]
b[i]=b0[i-d]
S
(所有顶点一个数组),对于每个顶点
v
,让我们将
sum(c)
的值放入
S[d]
元素中(
d
和
c
取决于
v
)。
S
,以便为每个
d
S[d] = sum_over_i(a0[i+d]*b0[i-d])
S
数组,就可以遍历顶点,并且对于每个顶点
v
都可以使用
sum(c)
像
S[d]
一样简单地获取其
d=dist(v,v0)
,因为对于每个顶点
v
我们都有
sum(c)=sum(a0[i+d]*b0[i-d])
。
S
的公式非常简单:
S
只是
a0
和
b0
序列中的
convolution。 (该公式并不完全符合定义,但是很容易修改为确切的定义形式。)
a0
和
b0
(可以在
O(L)
的时间和空间中进行计算),然后计算
S
数组。之后,我们可以遍历
S
数组,并简单地从
S[d]=2P+1
提取路径数。
O(L^2)
。但是,通过应用快速傅立叶变换算法对两个序列
can be calculated in O(L log L)
进行卷积。此外,您可以应用类似的
Number theoretic transform(不知道是否有更好的链接)仅与整数一起使用,并避免精度问题。
calculate a0 and b0 // O(L)
calculate S = corrected_convolution(a0, b0) // O(L log L)
v0 = leftmost vertex (root)
for v in vertices:
d = dist(v0, v)
ans = ans + (S[d]-1)/2
corrected_convolution
,是因为
S
并非完全是卷积,而是一个非常相似的对象,可以对其应用类似的算法。此外,您甚至可以定义
S'[2*d]=S[d]=sum(a0[i+d]*b0[i-d])=sum(a0[i]*b0[i-2*d])
,然后
S'
是适合的卷积。)
关于algorithm - 如何在退化树中找到所有从特定顶点开始的均等路径?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30329849/
关于 B 树与 B+ 树,网上有一个比较经典的问题:为什么 MongoDb 使用 B 树,而 MySQL 索引使用 B+ 树? 但实际上 MongoDb 真的用的是 B 树吗?
如何将 R* Tree 实现为持久(基于磁盘)树?保存 R* 树索引或保存叶值的文件的体系结构是什么? 注意:此外,如何在这种持久性 R* 树中执行插入、更新和删除操作? 注意事项二:我已经实现了一个
目前,我正在努力用 Java 表示我用 SML 编写的 AST 树,这样我就可以随时用 Java 遍历它。 我想知道是否应该在 Java 中创建一个 Node 类,其中包含我想要表示的数据,以及一个数
我之前用过这个库http://www.cs.umd.edu/~mount/ANN/ .但是,它们不提供范围查询实现。我猜是否有一个 C++ 范围查询实现(圆形或矩形),用于查询二维数据。 谢谢。 最佳
在进一步分析为什么MySQL数据库索引选择使用B+树之前,我相信很多小伙伴对数据结构中的树还是有些许模糊的,因此我们由浅入深一步步探讨树的演进过程,在一步步引出B树以及为什么MySQL数据库索引选择
书接上回,今天和大家一起动手来自己实现树。 相信通过前面的章节学习,大家已经明白树是什么了,今天我们主要针对二叉树,分别使用顺序存储和链式存储来实现树。 01、数组实现 我们在上一节中说过,
书节上回,我们接着聊二叉树,N叉树,以及树的存储。 01、满二叉树 如果一个二叉树,除最后一层节点外,每一层的节点数都达到最大值,即每个节点都有两个子节点,同时所有叶子节点都在最后一层,则这个
树是一种非线性数据结构,是以分支关系定义的层次结构,因此形态上和自然界中的倒挂的树很像,而数据结构中树根向上树叶向下。 什么是树? 01、定义 树是由n(n>=0)个元素节点组成的
操作系统的那棵“树” 今天从一颗 开始,我们看看如何从小树苗长成一颗苍天大树。 运转CPU CPU运转起来很简单,就是不断的从内存取值执行。 CPU没有好好运转 IO是个耗费时间的活,如果CPU在取值
我想为海洋生物学类(class)制作一个简单的系统发育树作为教育示例。我有一个具有分类等级的物种列表: Group <- c("Benthos","Benthos","Benthos","Be
我从这段代码中删除节点时遇到问题,如果我插入数字 12 并尝试删除它,它不会删除它,我尝试调试,似乎当它尝试删除时,它出错了树的。但是,如果我尝试删除它已经插入主节点的节点,它将删除它,或者我插入数字
B+ 树的叶节点链接在一起。将 B+ 树的指针结构视为有向图,它不是循环的。但是忽略指针的方向并将其视为链接在一起的无向叶节点会在图中创建循环。 在 Haskell 中,如何将叶子构造为父内部节点的子
我在 GWT 中使用树控件。我有一个自定义小部件,我将其添加为 TreeItem: Tree testTree = new Tree(); testTree.addItem(myWidget); 我想
它有点像混合树/链表结构。这是我定义结构的方式 struct node { nodeP sibling; nodeP child; nodeP parent; char
我编写了使用队列遍历树的代码,但是下面的出队函数生成错误,head = p->next 是否有问题?我不明白为什么这部分是错误的。 void Levelorder(void) { node *tmp,
例如,我想解析以下数组: var array1 = ["a.b.c.d", "a.e.f.g", "a.h", "a.i.j", "a.b.k"] 进入: var json1 = { "nod
问题 -> 给定一棵二叉树和一个和,确定该树是否具有从根到叶的路径,使得沿路径的所有值相加等于给定的和。 我的解决方案 -> public class Solution { public bo
我有一个创建 java 树的任务,它包含三列:运动名称、运动类别中的运动计数和上次更新。类似的东西显示在下面的图像上: 如您所见,有 4 种运动:水上运动、球类运动、跳伞运动和舞蹈运动。当我展开 sk
我想在 H2 数据库中实现 B+ Tree,但我想知道,B+ Tree 功能在 H2 数据库中可用吗? 最佳答案 H2 已经使用了 B+ 树(PageBtree 类)。 关于mysql - H2数据库
假设我们有 5 个字符串数组: String[] array1 = {"hello", "i", "cat"}; String[] array2 = {"hello", "i", "am"}; Str
我是一名优秀的程序员,十分优秀!