LeetCode 236 Lowest Common Ancestor of a Binary Tree
方法:递归
时间复杂度:O(n)
空间复杂度:O(n)
想法:这个题其实照理说也不是很难,是个经典题,但是我看了我的提交记录,前四次做这个题全都没想出来,我前几天第五次复习的时候才重想这个问题把它做出来。其实还是个递归,但是就是这个题的递归对我之前来说一直觉得很别扭,因为函数名说是返回lca,但真正递归的时候,返回的这个东西,从含义上来讲又不严格是lca。
假设说在原树的root这个地方我来调用,然后p和q分别属于左子树和右子树,那你去左子树里找lca,从lca的定义上来讲是没戏的,因为你不能左子树里面找到p和q的lca,你只找到了p这个节点。右子树同理。所以说这个题的返回值,应该说是,如果在这个树里面找到了严格意义上的lca,那我就返回这个lca;如果找不到,但能找到其中一个节点它在我这个子树里面,我就返回这个树节点;如果啥也找不到,返回null。所以说返回值携带的信息要多于“最低祖先”这个东西。
那么因为递归在树的这个结构上是从上到下的,所以假设说如果root等于了p或者q,应该直接返回root,因为按照上面对返回值的探讨,假如说root这个子树只有p或q当中的一个,那就把那个树节点返回,传上去。如果有两个,比方说root == p,那反正我递归的时候是先找到了p,q在这个子树里,那p和q的lca就是p,所以还是返回root。
在此之后,对左右子树分别调用lowestCommonAncestor(),如果两边都不是null,说明p和q分别在两个子树里,这样的话lca就是root。如果有一个为null,另一个不为null,那就是说一个子树里面出现了p和q,而且在对这个子树调用的时候,我们已经把它的lca一层层传上来了,所以返回那个不为null的值。假设说都为null,返回null,说明这棵树里找不到。
代码:
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if (root == null || root == p || root == q) {
return root;
}
TreeNode l = lowestCommonAncestor(root.left, p, q);
TreeNode r = lowestCommonAncestor(root.right, p, q);
if (l != null && r != null) {
return root;
}
if (l != null) {
return l;
}
if (r != null) {
return r;
}
return null;
}
}