Да, вы правы.Это правильная верхняя граница.На каждом уровне вы будете выполнять всю работу O (n) для maxValues.Вы можете проверить this для очень похожего анализа во время выполнения (он дает O (nlogn), поскольку h = logn, поскольку предполагается, что он хорошо сбалансирован).Использование h - хороший вызов, если дерево полностью разбалансировано (h = O (n)), тогда время выполнения будет O (n ^ 2), но если оно идеально сбалансировано (h = O (logn)), у вас будет O(nlogn).
Еще одна вещь, вы можете фактически кэшировать / вычислять значения max / min во время рекурсии, это даст вам амортизированное время выполнения 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
}
Itможет быть не самое чистое решение, но, безусловно, будет работать по линейному времени.С дополнительным штрафом пространства O (h) (для удержания вспомогательных структур в стеке функций), но, тем не менее, такие издержки являются нормальными при повторном использовании в любом случае.