在BST中找到小于K的最大元素

给定二叉搜索树和整数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 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; } 

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

顺便说一句,由于这是一个面试问题,通过调用图书馆function来实现它会告诉大多数采访者你是一个聪明人或者错过了这一点或者不知道如何解决它。 不要乱搞那种事情,只要开始研究你所知道的面试官想要的东西。

这是一个实现:

 // 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; } 

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

 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) } 

我相信使用标准的图书馆设施。 因此,我的解决方案使用std::set 。 🙂

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

我建议您遍历set :: upper_bound的本地实现中的代码以获取指导。 这不是解决您确切问题的方法,但非常接近。

通常在现实生活中,大多数问题不需要在您自己的代码中解决。 STL可以为您完成许多常见任务。 知道如何解决它们当然是有用的,因此测试。

第一个答案说的是,这就是为什么它不能比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 }