Given the root
of a binary tree, return the lowest common ancestor (LCA) of two given nodes, p
and q
. If either node p
or q
does not exist in the tree, return null
. All values of the nodes in the tree are unique.
According to the definition of LCA on Wikipedia: "The lowest common ancestor of two nodes p
and q
in a binary tree T
is the lowest node that has both p
and q
as descendants (where we allow a node to be a descendant of itself)". A descendant of a node x
is a node y
that is on the path from node x
to some leaf node.
Example 1:
Input: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1 Output: 3 Explanation: The LCA of nodes 5 and 1 is 3.
Example 2:
Input: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4 Output: 5 Explanation: The LCA of nodes 5 and 4 is 5. A node can be a descendant of itself according to the definition of LCA.
Example 3:
Input: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 10 Output: null Explanation: Node 10 does not exist in the tree, so return null.
Constraints:
- The number of nodes in the tree is in the range
[1, 104]
. -109 <= Node.val <= 109
- All
Node.val
are unique. p != q
Follow up: Can you find the LCA traversing the tree, without checking nodes existence?
这题跟236. Lowest Common Ancestor of a Binary Tree唯一不同的是,给定的两个节点p和q不一定存在树里,如果两个都存在就返回它们的最低公共祖先LCA,否则返回空节点。
基本思路还是遵循最低公共祖先LCA的原则,如果给定的两个p和q落在节点node的左右子树上,或者节点node就是p和q的其中一个而另一个落在node左子树或右子树上,那么节点node就是p和q的最低公共祖先。
还是使用递归法去查找两个节点p和q,递归函数对于输入节点node处理如下:
1)如果node的左子树存在p和q,那么说明在递归调用处理左子树时就已经找到了LCA节点,就可以直接返回把LCA节点一路往上传。
2)如果node的右子树存在p和q,那么说明在递归调用处理右子树时就已经找到了LCA节点,就可以直接返回把LCA节点一路往上传。
3)如果node的左右子树各存在一个节点,说明p和q是分别在node的左右两边,因此node就是LCA节点,向上层返回该节点。
4)如果node的左右子树只存在一个节点p或者q,如果node等于p或q,那么node就是LCA节点,向上层返回该节点。如果node不等于p或q,说node作为它的父节点的子树存在一个节点p或q,因此可以返回找到1个节点。
5)如果node及其左右子树不存在任何一个节点等于p或q,那么说明ode作为它的父节点的子树不存在任一个节点p或q,因此可以返回找到0个节点。
class Solution:
def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
def helper(node):
if not node:
return (None, 0)
lnode, lcnt = helper(node.left)
if lnode:
return (lnode, lcnt)
rnode, rcnt = helper(node.right)
if rnode:
return (rnode, rcnt)
cnt = lcnt + rcnt
if node == p or node == q:
cnt += 1
if cnt == 2:
return (node, cnt)
return (None, cnt)
return helper(root)[0]