我们能否在不知道二叉搜索树高度的情况下使用inorder遍历找到第k个最大元素? 或者有没有办法让我们创建一个新的遍历模式,例如“RIGHT ROOT LEFT”
答案 0 :(得分:1)
我们能否在不知道二叉搜索树高度的情况下使用inorder遍历找到第k个最大元素? <
是的,我们可以。
我们可以使用一些额外的空间。
我们不一定需要RIGHT-ROOT-LEFT
来找出kth
最大的元素(尽管这样做会避免使用额外的空间)。
有几种方法。
最基本的是拥有一个队列。
每当您顺序遍历时,请继续将值插入队列中。
不用说,因为它是二叉搜索树,所以队列将被排序。
因此kth
最大元素位于queue.size() - 1 - k
索引处。 (假设0th
largrst是最大元素,1st
最大值是第二个最大值,依此类推)
无论O(n)
k
额外空间
为了优化使用的空间,我们可以使用有关k
的信息
请注意,我们只需要(queue.size() - 1 - k)
索引处的元素。从而
我们可以有一个大小为(k+1)
的队列。在插入元素之前,我们将检查队列是否具有超过k
元素,如果有,我们将从前面删除一个元素,因为我们不需要它。
遍历完成后,kth
最大元素将位于队列的前面。
以下是这两种方法的java实现:
import java.util.LinkedList;
import java.util.Queue;
class Node {
int data;
Node left;
Node right;
static Queue<Integer> efficient = new LinkedList<>();
static Queue<Integer> complete = new LinkedList<>();
Node(int n) {
this.data = n;
this.left = null;
this.right = null;
}
public static void inorder(Node node, int k) {
if (node == null) {
return;
}
inorder(node.left, k);
if (efficient.size() > k) {
efficient.poll();
}
efficient.add(node.data);
complete.add(node.data);
System.out.println(efficient.toString());
inorder(node.right, k);
}
public static void main(String[] args) {
Node root = new Node(7);
root.left = new Node(4);
root.left.left = new Node(1);
root.left.right = new Node(5);
root.left.right.right = new Node(6);
root.right = new Node(9);
int k = 2;
inorder(root, k);
System.out.println("Efficient queue size : " + efficient.size() + " " + efficient.peek());
System.out.println("Full queue size : " + complete.size() + " " + complete.toArray()[complete.size() - 1 - k]);
}
}
运行此命令,您就会知道队列的增长效率。
请注意,此处k
应小于树中的节点数。如果不是,则答案将是最小的元素。
其他方法使用heap
来获得更一般的解决方案。在这种情况下,树不需要是二叉搜索树。
答案 1 :(得分:1)
这个怎么样:
x = T.root; while (x->right != NULL) { x = x->right; }
)x = x.predecessor()
k-1次(显然,照顾边缘情况)x
(您已在树中找到k
个最大元素)在BST上实现前驱和后继方法并不困难,当节点有一个指向父节点的附加指针时,它很容易。
答案 2 :(得分:0)
您是在谈论简单的二叉树还是像AVL树这样的树?
如果我理解正确,你根本不需要知道身高...... 顺序遍历 - 右向左 - 应该从最高值到最低值。
每次进入该函数时,您可以增加一个静态变量(或向该函数发送另一个参数) - 直到您到达K.
您还可以维护学位树,并直接了解该树的位置。