Python 二叉树结构定义
class TreeNode:
def __init__(self, val = 0, left = None, right = None):
# 当前节点值
self.val = val
# 左节点
self.left = left
# 右节点
self.right = right
给你一个二叉树的根节点 root ,判断其是否是一个有效的二叉搜索树。
有效 二叉搜索树定义如下:
节点的左子树只包含 小于 当前节点的数。
节点的右子树只包含 大于 当前节点的数。
所有左子树和右子树自身必须也是二叉搜索树。
解题思路
二叉搜索树的概念: 每一个节点 --> 该节点左树(所有元素) < 当前节点 < 该节点右树(所有元素)
第一层元素 Max 和 Min 区间定义(无限制)
第二层根据父节点(根节点)更新各个元素 Max 和 Min 区间定义
第三层根据父节点更新各个元素Max 和 Min 区间定义
代码实现
def isValidBTS(root):
def recur(root, maxValue = float('inf'), minValue = float('-inf')):
# 空树也是二叉搜索树
if not root: return True
if root.val >= maxValue or root.val <= minValue: return False
# 持续更新每个节点的 Max 和 Min 值
return recur(root.left, maxValue = root.val , minValue=minValue) \
and recur(root.right, maxValue=maxValue, minValue=root.val)
return recur(root)
给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
示例 1:
输入:root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
输出:3
解释:节点 5 和节点 1 的最近公共祖先是节点 3 。
解题思路
遍历整个树结构,当找到元素时便向上传递,传递的结果:
1. 节点A的值 == p或者q,并且 q或p 处于 A节点的子树上
2. 找到的p或q节点分列该节点的左右子树上
代码实现
def lowestCommonAncestor(root, p, q):
def helper(root):
if not root: return
# 找到 p 或 q 节点
if root.val == p.val or root.val == q.val: return root
left = helper(root.left)
right = helper(root.right)
# 当 p 和 q分列节点root的两侧
if left and right: return root
# 向上传递 left 节点(相同点,或 位于left节点的两侧时)
if left: return left
# 向上传递 right 节点(相同点,或 位于right节点的两侧时)
if right: return right
return
return helper(root)
给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
例如,给定如下二叉搜索树: root = [6,2,8,0,4,7,9,null,null,3,5]
输入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 8
输出: 6
解释: 节点 2 和节点 8 的最近公共祖先是 6。
解题思路
相对于二叉树而言,二叉搜索树的特点是: 节点左子树 < 该节点 < 节点右子树
所以,当遍历到该节点时,很块能判断:
p/q是位于节点的一侧,还是分列在该节点的两侧
如果位于节点一侧可以直接返回 该节点
位于节点一侧,继续向下查找,直到找到 p/q,或找到某个节点(p/q位于该节点两侧)
代码实现
def lowestCommonAncestor(root, p, q):
def helper(root):
if not root or root.val == p.val or root.val == q.val: return root
# 处于该节点的两侧
if (p.val >= root.val and q.val <= root.val) or (p.val <= root.val and q.val >= root.val): return root
# 处于该节点的同一边
if p.val > root.val: return helper(root.right)
else: return helper(root.left)
return helper(root)
or
def lowestCommonAncestor(root, p, q):
while root:
if p.val < root.val > q.val:
root = root.left
elif p.val > root.val < q.val:
root = root.right
else:
# 位于该节点的两侧时,直接返回
return root
解题思路
前序遍历: 5 9 5 4 7 2 3
中序遍历: 5 9 4 5 2 7 3
后序遍历: 5 4 9 2 3 7 5
代码实现
前序遍历
def preorder(root):
res = []
def helper(root):
if not root: return
res.append(root.val)
helper(root.left)
helper(root.right)
helper(root)
return res
def preorder(root):
res = []
q = [root]
while q:
node = q.pop()
res.append(node.val)
if node.right:
q.append(node.right)
if node.left:
q.append(node.left)
return res
中序遍历
def inorder(root):
res = []
def recur(root):
if not root: return
recur(root.left)
res.append(root.val)
recur(root.right)
recur(root)
return res
def inorder(root):
q = []
res = []
while q or root:
while root:
q.append(root)
root = root.left
# 找到最新的元素
root = q.pop()
res.append(root.val)
# 下一个开始的位置是right元素
root = root.right
return res
后序遍历
def postorder(root):
res = []
def helper(root):
if not root: return
helper(root.left)
helper(root.right)
res.append(root.val)
helper(root)
return res
def postorder(root):
q = [root]
res = deque([])
while q:
node = q.pop()
res.appendleft(node.val)
if node.left:
q.append(node.left)
if node.right:
q.append(node.right)
return list(res)