在不知道二叉搜索树的高度的情况下使用有序遍历的第K个最大元素

时间:2017-03-07 08:13:13

标签: data-structures tree binary-search-tree tree-traversal

我们能否在不知道二叉搜索树高度的情况下使用inorder遍历找到第k个最大元素? 或者有没有办法让我们创建一个新的遍历模式,例如“RIGHT ROOT LEFT”

3 个答案:

答案 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为对应于树的最小元素的节点(例如x = T.root; while (x->right != NULL) { x = x->right; }
  • 现在重复x = x.predecessor() k-1次(显然,照顾边缘情况)
  • 返回x(您已在树中找到k个最大元素)

在BST上实现前驱和后继方法并不困难,当节点有一个指向父节点的附加指针时,它很容易。

答案 2 :(得分:0)

您是在谈论简单的二叉树还是像AVL树这样的树?

如果我理解正确,你根本不需要知道身高...... 顺序遍历 - 右向左 - 应该从最高值到最低值。

每次进入该函数时,您可以增加一个静态变量(或向该函数发送另一个参数) - 直到您到达K.

您还可以维护学位树,并直接了解该树的位置。