问题描述
给定一个二叉搜索树和一个整数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;
}
解决方法
那是O(log n),这是最小值。但是,您可以通过消除尾部递归(将其变为循环)来提高效率(这似乎是这些访问员所关心的主要内容),并消除堆栈溢出(tada!)的可能性。另外,如果树包含负数,则您的代码不起作用...如果您指的是非负整数,则应这样说,但是如果访问者只是说“ integers”,则您需要稍有不同的代码和不同的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;
}
, 我认为这里的想法是记录您移至右侧子树后的最后一个节点。因此,代码将是(已更新)
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<int> const& set,int num)
{
std::set<int>::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
}