1、题目描述
2、解题思路
本题有两个问题:找出二叉树中的为 BST 的子树,返回最大的那个 BST 子树的节点数。
因此,必须从叶子节点往根节点的方向遍历,即 DFS。
对于叶子节点来说,它本身就是一颗 BST,节点数为 1。
对于非叶子节 node 点来说,有以下情况:
1、左右子节点为根节点的子树均为 BST,且 node 大于左子树的最大值,小于右子树的最小值,于是以 node 为根节点的树也是 BST,于是又找到一颗更大的 BST,节点数为左右子树结点数之和加一。
2、当前节点 node 不满足构成 BST 的条件,于是只能从左右子树中找最大 BST。
可以定义一个类来存储每个 BST 根节点的信息。
具体实现看代码。
3、解题代码
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
class Result {
TreeNode node; // BST根节点
int size; // BST的size
int max; // BST的最大值
int min; // BST的最小值
}
public int largestBSTSubtree(TreeNode root) {
Result r = dfs(root);
return r == null ? 0 : r.size;
}
public Result dfs(TreeNode node) {
if (node == null) return null;
Result l = null, r = null;
if (node.left != null) l = dfs(node.left);
if (node.right != null) r = dfs(node.right);
// 当前树为BST
boolean lValid = (l == null || (l.node == node.left && l.max < node.val));
boolean rValid = (r == null || (r.node == node.right && r.min > node.val));
if (lValid && rValid) {
Result result = new Result();
result.node = node;
result.max = r == null ? node.val : r.max;
result.min = l == null ? node.val : l.min;
result.size = (l == null ? 0 : l.size) + (r == null ? 0 : r.size) + 1;
return result;
}
// 左右子树中找到了BST
if (l != null && r != null) {
return l.size > r.size ? l : r;
}
if (l != null) return l;
if (r != null) return r;
return null;
}
}