我有一个 AVL 树,我想在 O(1) 中返回中值元素。
我知道每次插入新元素时都可以保存指向它的指针,而无需更改插入的运行时间(通过保存子树的大小并遍历直到找到第 n/2 个大小的子树)。
但我想知道我是否可以利用以下事实来做到这一点:在每次插入中,中位数都会“向右”移动,而在每次删除中,中位数都会“向左”移动。
以更一般的方式:如何使用前驱和后继跟踪 AVL 树中的第 i 个元素?
给定一个AVL(自平衡二叉搜索树),找到中位数。请记住,即使树是平衡的,您也不能只取根元素,因为即使树是平衡的,您也不知道中位数是否恰好是左儿子或右儿子的根元素。用于查找 AVL 中值的迭代算法。该算法基于每个 AVL 树的属性,您可以使用中序遍历获得包含该树的元素的排序集合。利用这个属性,我们可以获得节点的排序集合,然后找到中位数。该算法的时间和空间复杂度为 O(N),其中 N 是树中的节点数。
public class AvlTreeMedian {
BinaryTreeInOrder binaryTreeInOrder;
public AvlTreeMedian() {
this.binaryTreeInOrder = new BinaryTreeInOrder();
}
public double find(BinaryNode<Integer> root) {
if (root == null) {
throw new IllegalArgumentException("You can't pass a null binary tree to this method.");
}
List<BinaryNode<Integer>> sortedElements = binaryTreeInOrder.getIterative(root);
double median = 0;
if (sortedElements.size() % 2 == 0) {
median = (sortedElements.get(sortedElements.size() / 2).getData() + sortedElements.get(
sortedElements.size() / 2 - 1).getData()) / 2;
} else {
median = sortedElements.get(sortedElements.size() / 2).getData();
}
return median;
}
}
我认为 AVL 树不是最好的数据结构,但这让我想起了以下 leetcode 问题:https://leetcode.com/problems/find-median-from-data-stream/description/
我想你可以做的是: