答案 0 :(得分:0)
如果我们假设上面的内容是purely functional binary tree [wiki],那么在节点不可变的情况下,我们可以对这棵树进行“复制”,以便只有值大于 x的元素在树中 1 并低于 x 2 。
让我们从一个非常简单的案例开始说明这一点。想象一下,我们根本没有任何界限,而只是可以返回整个树。因此,我们无需构建 new 树,而是返回对树根的引用。因此,只要不对树进行编辑(至少只要不使用子树,就可以),我们就可以在 O(1)中无限制地返回树。
以上情况当然很简单。我们只需对整个树进行“复制”(由于数据是不可变的,因此并不是真正的复制,我们可以只返回树)。因此,让我们着眼于解决一个更复杂的问题:我们要构建一棵包含所有大于阈值 x 1 的元素的树。基本上,我们可以为此定义一个递归算法:
None
(或代表空引用或对空树的引用)的剪切版本为None
; 所以在伪代码中它看起来像:
def treelarger(some_node, min):
if some_tree is None:
return None
if some_node.value > min:
return Node(treelarger(some_node.left, min), some_node.value, some_node.right)
else:
return treelarger(some_node.right, min)
该算法因此以树的高度在 O(h)中运行,因为对于每种情况(除了第一种情况),我们递归到一个(不是两个),并且如果我们有一个没有孩子的节点(或者至少在我们需要剪切子树的方向上没有子树)的情况下结束。
因此,我们不制作树的完整副本。我们重用旧树中的许多节点。我们仅构造一个新的“表面”,但是大部分“体积”是旧的二叉树的一部分。尽管树本身包含 O(n)个节点,但我们最多只能构建 O(h)个新节点。我们可以优化上述内容,以使给定子树之一的分割版本相同,而不会创建新节点。但这在时间复杂度方面甚至没有多大关系:我们最多生成 O(h)个新节点,并且节点总数小于原始数目,或者相同。 / p>
如果是完整的树,则树的高度 h 随 O(log n)缩放,因此该算法将在 O(登录n)。
那么我们如何生成一个元素在两个阈值之间的树?我们可以轻松地将以上内容重写为算法treesmaller
,该算法会生成包含所有较小元素的子树:
def treesmaller(some_node, max):
if some_tree is None:
return None
if some_node.value < min:
return Node(some_node.left, some_node.value, treesmaller(some_node.right, max))
else:
return treesmaller(some_node.left, max)
因此大致来说有两个区别:
some_node.value > min
更改为some_node.value < max
;和right
子级子递归,如果条件不成立,则向左递归。现在我们从以前的算法得出的结论也是可以应用于该算法的结论,因为它再次仅引入了 O(h)个新节点,并且节点总数只能减少。
尽管我们可以构造同时考虑两个阈值的算法,但是我们可以简单地重用以上算法来构造仅包含范围内元素的子树:我们首先将树传递给{ {1}}函数,然后通过treelarger
获得结果(反之亦然)。
由于在这两种算法中,我们都引入了 O(h)新节点,并且树的高度不能增加,因此我们最多构造了 O(2 h),因此是 O(h)个新节点。
鉴于原始树是一棵 complete 树,因此它认为我们创建了 O(log n)新节点。
答案 1 :(得分:0)
考虑搜索范围的两个端点。该搜索将继续进行,直到找到跨越您的间隔的两个叶节点中最低的公共祖先。此时,搜索分支,其中一部分向左移动,而另一部分向右移动。现在,让我们只关注查询的左边分支部分,因为逻辑是相同的,但是对于右边分支却是相反的。
在此搜索中,有助于将每个节点视为不是代表单个点,而是代表一系列点。然后,一般过程如下:
如果查询范围完全包含此节点表示的范围,请停止在x中搜索并开始搜索此节点的y子树。
如果查询范围仅在此节点的右侧子树所表示的范围内,请继续在右侧进行x搜索,而不要研究y子树。
如果查询范围与左子树的范围重叠,则它必须完全包含右子树的范围。因此,请处理右侧子树的y子树,然后递归地探索左侧的x子树。
在所有情况下,我们最多考虑一个y子树,然后递归地继续仅在一个方向上探索x子树。这意味着我们实质上是在x-tree下方找到一条路径,每步最多添加一个y-subtree。由于树的高度为O(log n),因此以这种方式访问的y子树的总数为O(log n)。然后,在我们从右上分支的情况下,包括访问的y子树的数量,我们将得到另一个O(log n)子树,以搜索总共O(log n)个子树。
希望这会有所帮助!