参考代码:
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if (root == null) {
return root;
}
if (root == p || root == q) {
return root;
}
TreeNode left = lowestCommonAncestor(root.left, p, q);
TreeNode right = lowestCommonAncestor(root.right, p, q);
if (left != null && right != null) {
return root;
} else if (left != null) {
return left;
} else if (right != null) {
return right;
}
return null;
}
}
解题思路:递归法
递归三部曲:
- 确定递归函数返回值以及参数
可以利用上题目中返回值是TreeNode ,那么如果遇到p或者q,就把q或者p返回,返回值不为空,就说明找到了q或者p。
- 确定终止条件
如果找到了 节点p或者q,或者遇到空节点,就返回。
if (root == null) {
return root;
}
if (root == p || root == q) {
return root;
}
- 确定单层递归逻辑
值得注意的是 本题函数有返回值,是因为回溯的过程需要递归函数的返回值做判断,但本题我们依然要遍历树的所有节点。
搜索一条边的写法:
if (递归函数(root.left)) return ;
if (递归函数(root.right)) return ;
搜索整个树写法:
left = 递归函数(root.left);
right = 递归函数(root.right);
left与right的逻辑处理;
在递归函数有返回值的情况下:如果要搜索一条边,递归函数返回值不为空的时候,立刻返回,如果搜索整个树,直接用一个变量left、right接住返回值,这个left、right后序还有逻辑处理的需要,也就是后序遍历中处理中间节点的逻辑(也是回溯)。
而在此题中想利用left和right做逻辑处理, 不能立刻返回,而是要等left与right逻辑处理完之后才能返回,所以应该使用搜索整个树的写法。
先通过搜索整个树的写法,到达树的最底层,再一层层向上返回,在向上返回的过程中则需要判断出我们的所求值。
if (left != null && right != null) {
return root;
} else if (left != null) {
return left;
} else if (right != null) {
return right;
}//(left == null && right == null)
return null;
如此图:先到达最底层6,5,满足 if (root == null||root == p || root == q) return root;所以返回6,5;
返回上一层后,7满足if (left != null && right != null) return root;,所以返回7;
而1则满足if (left == null && right == null) return null;,所以返回null;
15,20也同理返回null;
再返回上一层,10满足if(left==null&&right!=null)return right;所以仍然返回7;(这也就是为什么当left为null时要返回right的值,同理right为null时要返回left的值)
最后以此类推,返回的值即为所求值。