每个节点比它左子树的任意节点大,而且比它右子树的任意节点小
98. 验证二叉搜索树
给定一个二叉树,判断其是否是一个有效的二叉搜索树。
假设一个二叉搜索树具有如下特征:
- 节点的左子树只包含小于当前节点的数。
- 节点的右子树只包含大于当前节点的数。
- 所有左子树和右子树自身必须也是二叉搜索树。
示例 1:
输入:
2
/
1 3
输出: true
示例 2:
输入:
5
/
1 4
/
3 6
输出: false
解释: 输入为: [5,1,4,null,null,3,6]。
根节点的值为 5 ,但是其右子节点值为 4 。
class Solution:
def isValidBST(self, root: TreeNode) -> bool:
if not root:
return True
stack = [(root,float('-inf'),float('inf'))]
while stack:
node,lower,upper = stack.pop()
if not node:
continue
val = node.val
if val <= lower or val >= upper:
return False
stack.append((node.right,val,upper))
stack.append((node.left,lower,val))
return True
#借用中序遍历,左根右 且大小依次增加
class Solution:
def isValidBST(self, root: TreeNode) -> bool:
if not root:
return True
stack = []
pre = float('-inf')
while stack or root:
while root:
stack.append(root)
root = root.left
root = stack.pop()
val = root.val
if val <= pre:
return False
pre = val
root = root.right
return True
96. 不同的二叉搜索树
给定一个整数 n,求以 1 ... n 为节点组成的二叉搜索树有多少种?
示例:
输入: 3
输出: 5
解释:
给定 n = 3, 一共有 5 种不同结构的二叉搜索树:
1 3 3 2 1
/ / /
3 2 1 1 3 2
/ /
2 1 2 3
思路
动态规划
问题是计算不同二叉搜索树的个数。为此,我们可以定义两个函数:
-
(G(n)): 长度为n的序列的不同二叉搜索树个数。
-
(F(i, n)): 以i为根的不同二叉搜索树个数
以序列中每个节点 (i) 作为根节点,遍历:
是对遍历所有 i (1 <= i <= n) 的 F(i, n)F(i,n) 之和。换而言之:
[G(n) = sum_{i=1}^{n} F(i, n)
]
对边界情况,当序列长度为 1 (只有根)或为 0 (空树)时,只有一种情况。亦即:
[G(0)=1,G(1)=1
]
给定序列 (1 ... n),我们选出数字 (i) 作为根,则对于根 (i) 的不同二叉搜索树数量 (F(i, n)), 是左右子树个数的组合,如下图所示:
得到:
[F(i,n)=G(i−1)⋅G(n−i)\G(n)= sum_{i=1}^n G(i−1)⋅G(n−i)
]
class Solution:
def numTrees(self, n: int) -> int:
#动态规划
G = [0]*(n+1)
G[0] = G[1] = 1
for i in range(2,n+1):
for j in range(1,i+1):
G[i] += G[j-1]*G[i-j]
return G[n]