思路1:DFS
lowestCommonAncestor函数返回值:若root树中有公共祖先就返回公共祖先,否则返回p / q本身- 那么如果左子树为空,说明全部都在右子树上,返回
rchild,反之,返回lchild - 如果两个子树都不是空的,说明分布在左右两边,返回
root
代码1:
# Definition for a binary tree node.# class TreeNode:# def __init__(self, x):# self.val = x# self.left = None# self.right = Noneclass Solution: # 这里的lowestCommonAncestro函数定义得很暧昧:若root树中有公共祖先就返回祖先,否则返回 p / q 本身 def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode': if not root: return None if root == p or root == q: return root # 以左子树根节点为根节点的树中,p q 的公共节点,若存在公共节点则返回公共节点,否则返回 p / q 本身 lchild = self.lowestCommonAncestor(root.left, p, q) rchild = self.lowestCommonAncestor(root.right, p, q) # 如果在左子树和右子树中找到的公共节点都存在: # 说明两个节点分别在左子树和右子树上 if lchild and rchild: return root elif lchild == None: return rchild else: return lchild return None
思路2:另外一种DFS
- 题解提供的思路,非常清晰
dfs(root, p, q)表示,以root为根节点的子树,是否包含p或者q当中的至少一个,如果是则返回True,否则返回False- 两种情况可以确定祖先
- 如果分别在左右节点上,
lchildInclude and rchildInclude同时成立 - 一者是根节点,同时另外一者在其左子树或者右子树上
代码2:
# Definition for a binary tree node.# class TreeNode:# def __init__(self, x):# self.val = x# self.left = None# self.right = Noneclass Solution: def __init__(self): self.ancestor: TreeNode() = None # root子树中是否含有p 和 q 两个节点中至少一个 def dfs(self, root: TreeNode(), p: TreeNode(), q: TreeNode()) -> bool: if not root: return False lchildInclude = self.dfs(root.left, p, q) rchildInclude = self.dfs(root.right, p, q) # 第一种情况:分别在左右节点上 if lchildInclude and rchildInclude: self.ancestor = root # 第二种情况:某一个是根节点 if (root == p) and (lchildInclude or rchildInclude): self.ancestor = root elif (root == q) and (lchildInclude or rchildInclude): self.ancestor = root return lchildInclude or rchildInclude or root == p or root == q def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode': self.dfs(root, p, q) return self.ancestor
思路3:DFS + 建立爸爸表
- 树结构的问题中,建立爸爸表是一件很重要的事情
- 所谓爸爸表,就是一个字典,其记录了每个节点的父亲是谁,
fa[node] = oldNode表示node节点的爸爸是oldNode。 - 可以通过DFS的方式去建立爸爸表,然后孩子节点从下往上找爸爸,找到的位置通过
vis字典去标记,第二个孩子往上走的时候,如果vis字典中已经有相关记录了,那么就说明这是一个公共祖先。 - 此方法应该是此题最最直观的想法了。
代码3:
# Definition for a binary tree node.# class TreeNode:# def __init__(self, x):# self.val = x# self.left = None# self.right = Noneclass Solution: def __init__(self): self.ancestor: TreeNode() = None self.fa = dict() self.vis = set() def dfs(self, root: TreeNode()) -> None: if not root: return if root.left: self.fa[root.left] = root self.dfs(root.left) if root.right: self.fa[root.right] = root self.dfs(root.right) def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode': # 建立爸爸表 self.dfs(root) self.fa[root] = None # 叶子节点从下往上遍历 while p != None: self.vis.add(p) p = self.fa[p] while q != None: if q in self.vis: return q q = self.fa[q] return root