Leetcode 二叉树 - 前进三格

118 阅读2分钟

二叉树示意图

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 的两个节点 pq,最近公共祖先表示为一个节点 x,满足 x 是 pq 的祖先且 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,并且 qp 处于 A节点的子树上
2. 找到的pq节点分列该节点的左右子树上

解题思路

代码实现

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 的两个结点 pq,最近公共祖先表示为一个结点 x,满足 xpq 的祖先且 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)