Я разместил полное решение и объяснение в своем блоге:
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;
}