建立基于有向图树的列表的时间顺序

时间:2019-05-18 10:26:17

标签: algorithm math graph-algorithm

因此,在我从事的一个个人项目中,我遇到了以下问题,由于我的数学技能并不十分出色,因此我一直在努力寻找解决方案。

假设您有下面的数字树a b c d e f g h:

    a
   / \
   b  c
 / |  |
g  d  f
|  |
h  e

每下一个树意味着下一个数字大于前一个数字。所以a c还是c

让我们说我们有一个有序的数字列表,例如[a,b,c,d,e]。我们如何编写一种算法来检查列表中数字的顺序(假设L [i]

I。 E,[a,c,b,d,e]和[a,b,d,c,e]都是正确的,但是[c,a,b,d,e]都不正确(因为我们知道c>一个,但与其他数字的结构无关。

出于算法的考虑,假设我们对树的访问是provably_greater(X,Y)函数,如果树知道一个数字大于另一个数字,则该函数返回true。即provably_greater(a,d)= True,但是provably_greater(d,f)= False。自然地,如果证明数字不大于,它也会返回false。

这不是 一个家庭作业问题,我已经对这个问题进行了很多抽象以使其更加清楚,但是解决该问题对于我要执行的任务至关重要。我已经尝试过几次自己破解它,但是我想出的一切最终都不足以满足我以后发现的情况。

谢谢。

2 个答案:

答案 0 :(得分:0)

您的陈述“我想出的一切最终都不足以让我在以后发现的某些极端情况下”,这似乎使您似乎根本没有解决方案。这是蛮力算法,它在所有情况下均适用。我可以想到几种提高速度的方法,但这只是一个开始。

首先,建立一个数据结构,该结构允许基于树快速评估provably_greater(X, Y)。此结构可以是集合或哈希表,这将占用大量内存,但允许快速访问。对于树的每片叶子,请选择一条直到根的路径。在每个节点上,查看所有后代节点,并将有序对添加到集合中,以显示这两个节点的小于关系。在示例树中,如果从节点h开始,则上移到节点g并将(g,h)添加到集合中,然后上移到节点b并添加对(b,h)(b,g)到集合中,然后向上移动到节点a并将(a,h)(a,g)(a,b)对添加到集合中。对叶节点ef执行相同的操作。由于叶子节点(a,b)he对将被添加到集合两次,但是集合结构可以轻松地处理此问题。

功能provably_greater(X, Y)现在变得简单快捷:如果True对在集合中,则结果为(Y,X),否则为False

现在,您查看列表中的所有数字对-对于列表[a,b,c,d,e],您将查看对(a,b)(a,c)(b,c)等。如果provably_greater(X, Y)对这些对中的任何对都为true,则该列表无序。否则,列表是按顺序排列的。

使用Python之类的语言实现起来应该很容易。让我知道您是否需要一些Python 3代码。

答案 1 :(得分:0)

我将忽略您的provably_greater函数,并假定访问树,以便提供高效的算法。

  1. 首先,对树进行一次Euler游览,记住每个节点的开始索引和结束索引。如果使用同一棵树来检查许多列表,则只需执行一次。参见https://www.geeksforgeeks.org/euler-tour-tree/

  2. 创建一个最初为空的索引二进制搜索树

  3. 遍历列表。对于每个节点,请检查树是否在其开始和结束Euler巡回索引之间包含任何索引。如果是这样,则列表是乱序的。如果不是,则将其起始索引插入树中。这样可以防止任何较小的节点出现在列表的后面。

就是这样-对于每个列表,总共为O(N log N)。

二进制搜索树可以使用Java中的TreeSet或C ++中的std::set