【问题标题】:To find largest element smaller than K in a BST在 BST 中找到小于 K 的最大元素
【发布时间】:2011-06-13 18:22:33
【问题描述】:

给定一个二叉搜索树和一个整数 K,我想找到小于 K 的最大元素。

在下面的树中,

for K = 13, result = 12
for K = 10, result = 8
for K = 1 (or) 2, result = -1

      10

  5       12

2   8   11  14

我尝试了以下逻辑。但是有没有更好的方法来做到这一点?

int findNum(node* node, int K)
{
        if(node == NULL)
        {
                return -1;
        }
        else if(K <= node->data)
        {
                return findNum(node->left,K);
        }
        else if(K > node->data)
        {
                int t = findNum(node->right,K);
                return t > node->data ? t : node->data;
        }

        return -1;
}

【问题讨论】:

  • 如果找到 K-1,您应该终止。我无法从您的代码中判断您是否正在执行此操作(尽管这可能很明显,但我不懂 C++)。
  • 请定义“更好”。更高效?更准确?
  • @PengOne:您的建议可能更有效,这可能是正确的,但技术上我们并没有被告知 BST 包含整数,只是搜索键是。
  • @Seth Robertson:int 在他的代码中暗示了这一点。
  • @PengOne 如果树通常不包含 K-1,这样的优化可能会比它的价值更高。而且由于K-1 没有出现在代码中的任何位置,而且这是 C,而不是 Malbolge,我发现很难理解人们无法判断上述代码中不存在这样的测试。

标签: c++ c binary-search-tree


【解决方案1】:

我相信使用标准库设施。因此,我的解决方案使用std::set。 :-)

int largest_num_smaller_than(std::set<int> const& set, int num)
{
    std::set<int>::const_iterator lb(set.lower_bound(num));
    return lb == set.begin() ? -1 : *--lb;
}

【讨论】:

    【解决方案2】:

    我认为这里的想法是记录您移动到右子树之后的最后一个节点。因此,代码将(已更新)

    int findNum (Node *node, int K)
    {
        Node* last_right_move = NULL;
    
        while (node)
        {
            if (K<=node->data)
                node = node->left;
            else
            {
                last_right_move = node;
                node = node->right;
            }
        }
    
        if (last_right_move)
            return last_right_move->data;
        else
            return NOT_FOUND;  // defined previously. (-1 may conflict with negative number)
    }
    

    【讨论】:

      【解决方案3】:

      这是 O(log n),这是最小值。但是,您可以通过消除尾递归将其变成循环来提高效率(这似乎是这些面试官关心的主要内容)并消除堆栈溢出的可能性(tada!)。此外,如果树包含负数,您的代码将不起作用......如果您的意思是 非负 整数,您应该这样说,但如果面试官只是说“整数”,那么您需要稍微不同的代码和不同的 API。 (您可以保留相同的函数签名,但在失败时返回 K 而不是 -1。)

      顺便说一句,由于这是一个面试问题,通过调用库函数来实现它会告诉大多数面试官你是个聪明人,或者没有抓住重点,或者不知道如何解决它。不要乱搞这类事情,只要按照你知道面试官想要的去做。

      这是一个实现:

      // Return the greatest int < K in tree, or K if none.
      int findNum (Node* tree, int K)
      {
          int val = K;
      
          while( tree )
              if( tree->data >= K )
                  tree = tree->left;
              else{
                  val = tree->data; 
                  tree = tree->right;
              }
      
          return val;
      }
      

      【讨论】:

        【解决方案4】:

        我建议您浏览一下本地实现 set::upper_bound 中的代码以获得指导。这不是您确切问题的解决方案,但非常接近。

        一般在现实生活中,这些问题大部分不需要在自己的代码中解决。 STL 可以为您完成许多常见任务。知道如何解决它们当然很有用,因此进行了测试。

        【讨论】:

          【解决方案5】:

          第一个答案所说的,这就是为什么它不能比 O(log n) 更好的逻辑。您正在寻找小于 K 的最大数。这非常接近于调用 BST-search/get 。

          虽然你原来的算法看起来不错,但我认为这样会更快:

              int findNum (node root, int K) {
                  if(root == null) return -1;
          
                  if(K > root.val) { 
                     if(root.right != null) return findNum(root.right, K);               
                     else return root.val; 
                  }
          
                  return findNum(root.left, K); //look in left subtree
          
              }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2020-03-28
            • 1970-01-01
            • 2020-03-02
            • 2021-01-06
            • 2011-06-14
            • 2021-06-04
            • 2012-10-22
            • 2022-07-22
            相关资源
            最近更新 更多