Given a binary tree, find the largest subtree which is a Binary Search Tree (BST), where largest means subtree with largest number of nodes in it.
Note:
A subtree must include all of its descendants.
Here's an example:
10
/ \
5 15
/ \ \
1 8 7
The Largest BST Subtree in this case is the highlighted one.
The return value is the subtree's size, which is 3.
Follow up:
Can you figure out ways to solve it with O(n) time complexity?
Solution:递归 Post-order 分治 Bottom-up向上传递
思路: 分治divide左右子树,conquer左右子树的pack.范围和count,并计算出自己当前的pack继续上传,期间更新最大result。
pack传递可以通过返回值 写法1_a,也可以通过参数 写法1_b,都可以的
Time Complexity: O(N) Space Complexity: O(N) 递归缓存
屏幕快照 2017-09-09 上午10.28.58.png
Solution1_a Code:
class Solution {
class Pack {
int lower;
int upper;
int count;
Pack(int lower, int upper, int count) {
this.lower = lower;
this.upper = upper;
this.count = count;
}
}
private int result;
public int largestBSTSubtree(TreeNode root) {
result = 0;
helper(root);
return result;
}
private Pack helper(TreeNode root) {
if(root == null) return new Pack(Integer.MAX_VALUE, Integer.MIN_VALUE, 0);
// divide
// [min, max, count]
Pack left = helper(root.left);
Pack right = helper(root.right);
// conquer
Pack pack = new Pack(Integer.MAX_VALUE, Integer.MIN_VALUE, 1);
if(left.count != -1 && right.count != -1 && root.val > left.upper && root.val < right.lower) {
pack.count += (left.count + right.count);
if(pack.count > result) result = pack.count;
}
else {
//locked
return new Pack(0, 0, -1);
}
pack.lower = Math.min(left.lower, root.val);
pack.upper = Math.max(right.upper, root.val);
return pack;
}
}
Solution1_b Code:
class Solution {
class Pack {
int lower;
int upper;
int count;
Pack(int lower, int upper, int count) {
this.lower = lower;
this.upper = upper;
this.count = count;
}
}
private int result;
public int largestBSTSubtree(TreeNode root) {
result = 0;
helper(root, new Pack(Integer.MAX_VALUE, Integer.MIN_VALUE, 0));
return result;
}
private void helper(TreeNode root, Pack pack) {
if(root == null) return;
// divide
// [min, max, count]
Pack left = new Pack(Integer.MAX_VALUE, Integer.MIN_VALUE, 0);
Pack right = new Pack(Integer.MAX_VALUE, Integer.MIN_VALUE, 0);
helper(root.left, left);
helper(root.right, right);
pack.count = 1;
if(left.count != -1 && right.count != -1 && root.val > left.upper && root.val < right.lower) {
pack.count += (left.count + right.count);
if(pack.count > result) result = pack.count;
}
else {
//locked
pack.lower = 0;
pack.upper = 0;
pack.count = -1;
}
pack.lower = Math.min(left.lower, root.val);
pack.upper = Math.max(right.upper, root.val);
}
}