AVL树区间[x,y]节点查询算法的时间复杂度分析(目标O(logn+k))
Got it!咱们来搞定这个AVL树的区间查询问题,要达到O(logn +k)的时间复杂度其实很清晰,核心就是先精准定位区间的起始节点,再按升序遍历输出所有符合条件的节点,下面一步步拆解:
算法核心思路
AVL树是平衡二叉搜索树,天然支持对数级的查找操作。我们的目标是把时间拆成两部分:
- O(logn):定位到第一个大于x的节点(区间的起始点)
- O(k):遍历并输出所有介于x和y之间的节点(共k个)
这样加起来总复杂度就是O(logn +k),完美匹配你的要求。
1. 定位区间起始节点
首先要找到树中第一个值大于x的节点,这一步利用AVL树的搜索特性,时间复杂度O(logn)。具体逻辑:
- 从根节点出发,维护一个栈来记录遍历路径(为后续的中序遍历做准备)
- 如果当前节点值 <=x:说明更大的节点一定在右子树,直接移动到右孩子
- 如果当前节点值 >x:把这个节点压入栈,然后尝试往左子树找更小的但仍大于x的节点(因为左子树可能存在更接近x的合法节点)
- 直到遍历到空节点,此时栈中保留的路径就是后续遍历的基础
2. 遍历输出区间内节点
找到起始节点后,我们通过栈模拟中序遍历的方式,依次输出所有值<=y的节点,这部分的时间复杂度是O(k):
- 从栈中弹出节点,如果节点值超过y就跳过
- 输出符合条件的节点后,处理它的右子树:把右子树中所有值<=y的左孩子依次压入栈(保证后续弹出的是升序的节点)
- 重复这个过程直到栈为空
伪代码实现(Python风格)
def print_range(root, x, y): stack = [] current = root # 第一步:定位第一个大于x的节点,同时构建遍历栈 while current is not None: if current.val > x: stack.append(current) current = current.left else: current = current.right # 第二步:遍历输出所有<=y的节点 while stack: node = stack.pop() if node.val > y: continue # 输出节点值(这里可以替换成你需要的处理逻辑) print(node.val) # 处理右子树,压入所有可能的候选节点 current = node.right while current is not None and current.val <= y: stack.append(current) current = current.left
时间复杂度验证
- 定位起始节点:AVL树的高度是O(logn),所以遍历路径的长度是O(logn),这部分操作是O(logn)
- 输出k个节点:每个符合条件的节点会被压栈和出栈各一次,总共O(k)次操作;处理右子树的压栈过程也是O(k)的均摊时间(每个节点最多被压栈一次)
- 总时间复杂度:O(logn +k),完全满足你的要求
额外注意点
- 如果你需要包含x和y(即使它们在树中),只需要把判断条件改成
current.val >=x(定位起始点时)和node.val <=y(输出时)即可 - AVL树的平衡特性保证了不会出现像普通二叉搜索树那样的退化路径,所以时间复杂度是稳定的对数级
内容的提问来源于stack exchange,提问作者Nadav Matityahu
相关产品推荐
相关产品推荐

