leetcode236.二叉树的最近公共祖先
这题是普通二叉树,我个人最开始拿到这道题的想法是联系起来以前做过的链表题,《找链表第一个相交的节点》,那道题用了个快慢指针,先求链表长度,然后快指针先走delta。
所以对于这个236题,我第一反应直观的想法是求到根节点到p、q两个节点的path,然后逆向去求两条path的第一个相交节点(或是正向求得当两个节点的值不同的时候,那么前一个节点就是最近公共祖先)
不过,这样需要额外的空间,我们可以直接在二叉树利用后序遍历的特性进行操作。
求公共祖先,如果我们能从下往上遍历就好了,但是二叉树没提供向上的指针,所以我们可以利用后序,先处理目前节点的左子树和右子树,再根据左子树和右子树的返回结果来处理当前节点
1:如果一个节点node的左子树有p or q,右子树也有p or q,那node就是他俩的最近公共祖先
2:如果一个节点node的左子树有p or q,而右子树没有p or q,那公共祖先要么在node之上,要么就是身处node的左子树的p or q本身
3:与2对称
4:如果一个节点node的左子树、右子树都没有p or q,那node为根节点的这棵子树不可能有目标公共祖先
递归法
class Solution:
def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
def post_traversal(node):
#终止条件,空节点肯定就没找到p、q,向上返回None
if not node:
return None
#遇到p or q节点,就向上返回
if node.val == p.val or node.val == q.val:
return node
#后序,先处理左右孩子
l_result = post_traversal(node.left)
r_result = post_traversal(node.right)
#如果左孩子、右孩子都找到了p or q,那这个node就是最近公共祖先,直接向上返回他
#在这里要想清楚如何把这个node层层传递到最外层函数
#这个node只能是他父节点的左孩子或者右孩子,那么对于node的父亲来说,father.left
#或者father.right其中一个为node,另一个为None,father向上传递node,
#然后grandfather继续传递node,一层层到最上面(这里传递逻辑还和下面几种情况相关)
if l_result and r_result:
return node
#如果只有一个子树找到,另一个没找到,那就传递找到了的子树的根节点
elif l_result and not r_result:
return l_result
elif not l_result and r_result:
return r_result
#都没找到,废了
else:
return None
return post_traversal(root)
leetcode235.二叉搜索树的最近公共祖先
利用二叉搜索树的性质进行遍历就行,很简单没什么讲的
递归法:
class Solution:
def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
def recursion(node):
if not node:
return
if p.val < node.val and q.val < node.val:
result_l = recursion(node.left)
if result_l:
return result_l
if p.val > node.val and q.val > node.val:
result_r = recursion(node.right)
if result_r:
return result_r
return node
return recursion(root)
迭代法:
class Solution:
def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
if not root:
return None
cur = root
while cur:
if p.val < cur.val and q.val < cur.val:
cur = cur.left
elif p.val > cur.val and q.val > cur.val:
cur = cur.right
else:
return cur