我已经在我的博客中发布了完整的解决方案和解释:
http://www.leetcode.com/2010/11/largest-binary-search-tree-bst-in.html
这个想法是进行深度优先遍历并传递最小值和最大值自下而上而不是自上而下。换句话说,在验证上述节点是否满足 BST 要求之前,我们先验证更深的节点。
这样做的主要原因是当其中一个节点不满足 BST 属性时,上面的所有子树(也包括该节点)也必须不满足 BST 要求。
与自上而下的方法相比,自下而上的方法是一个很棒的选择,因为节点总数的结果可以向上传递树。这使我们不必一遍又一遍地重新计算。子树的节点总数就是其左右子树的节点总数加一。
该算法在 O(N) 时间复杂度和 O(1) 空间中运行,效率最高。 (其中 N 是二叉树中的节点总数)。
以下是有效的 C++ 代码。实现的棘手部分是处理如何自下而上传递最小值和最大值。请注意,我没有初始化最小值和最大值,因为它们是在树的底部初始化的。
// Find the largest BST subtree in a binary tree.
// If the subtree is a BST, return total number of nodes.
// If the subtree is not a BST, -1 is returned.
int findLargestBSTSubtree(BinaryTree *p, int &min, int &max,
int &maxNodes, BinaryTree *& largestBST) {
if (!p) return 0;
bool isBST = true;
int leftNodes = findLargestBSTSubtree(p->left, min, max, maxNodes, largestBST);
int currMin = (leftNodes == 0) ? p->data : min;
if (leftNodes == -1 ||
(leftNodes != 0 && p->data <= max))
isBST = false;
int rightNodes = findLargestBSTSubtree(p->right, min, max, maxNodes, largestBST);
int currMax = (rightNodes == 0) ? p->data : max;
if (rightNodes == -1 ||
(rightNodes != 0 && p->data >= min))
isBST = false;
if (isBST) {
min = currMin;
max = currMax;
int totalNodes = leftNodes + rightNodes + 1;
if (totalNodes > maxNodes) {
maxNodes = totalNodes;
largestBST = p;
}
return totalNodes;
} else {
return -1; // This subtree is not a BST
}
}
BinaryTree* findLargestBSTSubtree(BinaryTree *root) {
BinaryTree *largestBST = NULL;
int min, max;
int maxNodes = INT_MIN; // INT_MIN is defined in <climits>
findLargestBSTSubtree(root, min, max, maxNodes, largestBST);
return largestBST;
}