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?
在二叉树中查找为最大BST的子树, 开始时觉得这题和剑指offer上Longest increasing subarray是一类题目.只是从数组换成了动态的中序遍历. 后来发现这种情况无法检验是否是一整颗子树.所以需要换一种策略来做.也就是devide and conquer,对于每个节点,考虑其左右子树是否是BST, 如果都是是BST,则再检验加上这个节点之后组成的子树是否是BST. 即leftMax < root.val && rightMin > root.val. 之后计算当前子树的大小,需要利用左右子树的大小,所以这题每次遍历需要返回多个变量: size, min, max. 当然也需要返回当前子树是否是BST的一个状态信息,可以加上一个flag变量, 或者我们也可以利用Balanced Binary Tree
中的做法,大于等于0的确实表示高度,-1表示不平衡.所以这里我们可以用size = -1表示子树非BST.每个节点处理一次,时间复杂度为O(n),空间复杂度为栈高度O(logn),代码如下:
# Definition for a binary tree node. # class TreeNode(object): # def __init__(self, x): # self.val = x # self.left = None # self.right = None class Solution(object): def largestBSTSubtree(self, root): """ :type root: TreeNode :rtype: int """ if not root: return 0 res = [0] Min, Max, size = self.helper(root, res) return res[0] def helper(self, root, res): if not root: return sys.maxint, -sys.maxint -1, 0 #注意节点不存在时,为了方便比较,Min定义为最小值,Max定义为最大值.或者inf #return 0, float('inf'), float('-inf') leftMin, leftMax, leftSize = self.helper(root.left, res) rightMin, rightMax, rightSize = self.helper(root.right, res) if leftSize == -1 or rightSize == -1 or leftMax > root.val or rightMin < root.val: return 0, 0, -1 else: size = leftSize + rightSize + 1 res[0] = max(res[0], size) return min(leftMin, root.val), max(root.val, rightMax), size #除去sys.maxint和sys.maxint的影响.
原始未优化代码:
# Definition for a binary tree node. # class TreeNode(object): # def __init__(self, x): # self.val = x # self.left = None # self.right = None class Solution(object): def largestBSTSubtree(self, root): """ :type root: TreeNode :rtype: int """ if not root: return 0 res = [0] Min, Max, flag, size = self.helper(root,res) return res[0] def helper(self, root, res): if not root.left and not root.right: res[0] = max(res[0],1) return root.val, root.val, True, 1 Min = Max = root.val size = -1 flag = True leftSize = rightSize = 0 if root.left: leftMin, leftMax, leftFlag, leftSize = self.helper(root.left, res) if not leftFlag or leftMax > root.val: flag = False else: Min = leftMin if root.right: rightMin, rightMax, rightFlag, rightSize = self.helper(root.right, res) if not rightFlag or rightMin < root.val: flag = False else: Max = rightMax if not flag: return -1, -1, False, size else: size = 1 + leftSize + rightSize res[0] = max(res[0], size) return Min, Max, True, size