请注意:这个问题与算法的最佳实现无关,与数据结构无关。
给定一个二叉树,需要确认它是bst
。
我知道效率更高(O(n)
)的算法,问题不关乎它。我正在练习我的O估计技能:
int isBST(struct node* node)
{
if (node == NULL)
return(true);
if (node->left!=NULL && maxValue(node->left) > node->data)
return(false);
if (node->right!=NULL && minValue(node->right) < node->data)
return(false);
if (!isBST(node->left) || !isBST(node->right))
return(false);
return(true);
}
..假设maxValue(...)/minValue(...)
是每个需要O(n)
运行的辅助函数。
如果h
是“级别”的数量,则它从根开始并以叶子结束。在每个级别,maxValue(...)
和minValue(...)
都在(n - 1) / 2^l
范围内被调用,其中l
是当前级别。有h
个级别,所以我希望得到类似(n - 1) / 1 + (n - 1) / 2 + (n - 1) / 4 + ... + (n - 1) / 2^h
的东西。看来O(n * h)
是正确的上限,对吗?
请验证我的想法。
答案 0 :(得分:1)
是的,您是正确的。那是正确的上限。在每个级别上,您将为maxValues进行总体O(n)工作。您可以检查this进行非常类似的运行时分析(由于h = logn假设平衡良好,因此它给出O(nlogn))。使用h是一个很好的选择,如果树完全不平衡(h = O(n)),则运行时将为O(n ^ 2),但是如果树完全平衡(h = O(logn)),则将具有O (nlogn)。
还有一件事,您实际上可以在递归时缓存/计算最大值/最小值,这将为您提供摊销的O(n)运行时:
struct helper {
int min;
int max;
};
int isBST(struct node* root) {
struct helper help;
return isBST_internal(root, &help);
}
int isBST_internal(struct node* root, struct helper *min_max) {
if (!root) return true;
if (root->left) {
// Recurse on left
struct helper left_helper;
int is_left_BST = isBST_internal(root->left, &left_helper)
if (!is_left_BST || left_helper.max > root->data)
return false;
min_max->min = left_helper.min;
} else {
// If no left subtree, the min value should be the current node value
min_max->min = root->data;
}
if (root->right) {
// recurse on right side
struct helper right_helper;
int is_right_BST = isBST_internal(root->right, &right_helper)
if (!is_right_BST || right_helper.min < root->data)
return false;
min_max->max = left_helper.max;
} else {
// If no right subtree, the max value should be the current node value
min_max->max = root->data;
}
// If we have not returned yet it means all conditions for BST are satisfied
// Also, min_max is properly set now.
return true
}
这可能不是最干净的解决方案,但肯定会在线性时间运行。加上额外的O(h)空间损失(以将辅助结构保存在函数堆栈上),但无论如何,这种开销在递归时还是正常的。