有效地找到二进制搜索树中第k个最小的元素?

时间:2018-11-29 00:16:24

标签: java algorithm data-structures binary-search-tree

我今天面临以下面试问题,我提出了如下所述的递归和迭代解决方案,但面试官不知何故不满意。我不确定为什么。

  

给出二叉搜索树,在其中找到第k个最小元素。

是否有更好的方法以递归或迭代的方式解决此问题?

  /*****************************************************
   *
   * Kth Smallest Recursive
   *
   ******************************************************/
  public int kthSmallestRecursive(TreeNode root, int k) {
    int count = countNodes(root.left);
    if (k <= count) {
      return kthSmallestRecursive(root.left, k);
    } else if (k > count + 1) {
      return kthSmallestRecursive(root.right, k - 1 - count);
    }

    return root.data;
  }

  public int countNodes(TreeNode n) {
    if (n == null)
      return 0;

    return 1 + countNodes(n.left) + countNodes(n.right);
  }

  /*****************************************************
   *
   * Kth Smallest Iterative
   *
   ******************************************************/

  public int kthSmallestIterative(TreeNode root, int k) {
    Stack<TreeNode> st = new Stack<>();

    while (root != null) {
      st.push(root);
      root = root.left;
    }

    while (k != 0) {
      TreeNode n = st.pop();
      k--;
      if (k == 0)
        return n.data;
      TreeNode right = n.right;
      while (right != null) {
        st.push(right);
        right = right.left;
      }
    }

    return -1;
  }

我在上述两种解决方案中都将复杂度称为O(节点深度),即O(log n)。

我的迭代版本占用更多空间。有没有没有多余空间的方法?

2 个答案:

答案 0 :(得分:1)

首先,我不确定是否要使用O(logn)。原始二进制搜索树至少为O(n)。

对于香草,您可以进行迭代或递归,两者都是模拟相同的忽略者遍历过程,但时间复杂度为O(n)和空间复杂度为O(logn)(请注意,即使递归解决方案也可以采用O(logn)堆栈空间)。

但是,如果可以稍微更改数据结构,则可以加快处理速度或使用较少的空间:

  1. 如果您使用的是二进制搜索树,并且每个节点都记录了其下的总节点数,则可以将其视为已排序的数组,并使用O(logn)到达第k个元素时间和O(1)空间。

  2. 如果使用的二进制搜索树的每个节点都包含父指针和状态指示符,则可以以与原始解决方案相同的方式遍历该树。在途中,您标记节点是否为a。未遍历。2.遍历其左节点。3.遍历两个节点。那么您可以在O(n)时间和O(1)空间中做到这一点。

答案 1 :(得分:0)

datetimeobject.AfterDate.ToString(@"s", CultureInfo.InvariantCulture)

在递归方法的 public int printInorder(Node node, int k) { if (node == null || k <= 0) //Stop traversing once you found the k-th smallest element return k; /* first recur on left child */ k = printInorder(node.left, k); k--; if(k == 0) { System.out.print(node.key); } /* now recur on right child */ return printInorder(node.right, k); } 方法中,您遍历每个节点上的Tree进行计数。 countNodes()操作是O(n),您正在对log(n)个节点执行操作。因此,递归解决方案的复杂度顺序为countNodes(),而我上面提到的方法可以在O(n)中解决。