为什么用分段树时间复杂度求解范围最小查询是O(Log n)?

时间:2018-05-06 11:12:52

标签: avl-tree segment-tree

我试图解决如何在给定数组和两个索引中找到O(Log(n))中这两个索引之间的最小值。 我看到使用分段树的解决方案,但无法理解为什么这个解决方案的时间复杂度是O(Logn),因为它看起来不是这样的,因为如果你的范围不完全在nod的范围内,你需要开始分割搜索范围。

1 个答案:

答案 0 :(得分:1)

第一个证据

声称是在每个级别最多扩展2个节点。我们将通过矛盾证明这一点。

考虑下面给出的细分树。

enter image description here

让我们说这棵树中有3个节点被扩展。这意味着范围是从最左边的彩色节点到最右边的彩色节点。但是请注意,如果范围扩展到最右边的节点,则将覆盖中间节点的整个范围。因此,此节点将立即返回该值,并且不会扩展。因此,我们证明在每个级别上,我们最多可以扩展2个节点,并且由于存在logn级别,因此扩展的节点为2⋅logn=Θ(logn)。

Source

第二证明:

查询间隔(x,y)有四种情况

FIND(R,x,y) //R is the node
% Case 1
    if R.first = x and R.last = y   
        return {R}
% Case 2
    if y <= R.middle
        return FIND(R.leftChild, x, y) 
% Case 3
    if x >= R.middle + 1 
        return FIND(R.rightChild, x, y) 
% Case 4
    P = FIND(R.leftChild, x, R.middle)
    Q = FIND(R.rightChild, R.middle + 1, y)    
    return P union Q.

直观地,前三种情况将树的高度降低1,因为树的高度为log n,如果仅发生前三种情况,则运行时间为O(log n)。

对于最后一种情况,FIND()将问题分为两个子问题。但是,我们断言,这种情况最多只能发生一次。调用FIND(R.leftChild,x,R.middle)之后,我们将查询R.leftChild的间隔[x,R.middle]。 R.middle与R.leftChild.last相同。如果x> R.leftChild.middle,则为案例1;如果x <= R.leftChild,那么我们将调用

FIND ( R.leftChild.leftChild, x, R.leftChild.middle );
FIND ( R.leftChild.rightChild, R.leftChild.middle + 1, , R.leftChild.last );

但是,第二个FIND()返回R.leftChild.rightChild.sum,因此花费的时间是恒定的,并且该问题不会分为两个子问题(严格来说,问题是分开的,尽管一个子问题为O(1 )解决的时间。

由于对R的rightChild进行了相同的分析,因此我们得出结论,在case4首次发生之后,运行时间T(h)(h是树的剩余层)将为

T(h) <= T(h-1) + c (c is a constant)
T(1) = c

产生:

T(h) <= c * h = O(h) = O(log n) (since h is the height of the tree)

因此,我们结束证明。

Source