给一棵二叉树和二叉树中的两个节点,找到这两个节点的最近公共祖先LCA。
两个节点的最近公共祖先,是指两个节点的所有父亲节点中(包括这两个节点),离这两个节点最近的公共的节点。
返回 null
如果两个节点在这棵树上不存在最近公共祖先的话。
样例
给出下面这棵树:
4
/ \
3 7
/ \
5 6
LCA(3, 5) = 4
LCA(5, 6) = 7
LCA(6, 7) = 7
LCA(5, 8) = null
注意事项
这两个节点未必都在这棵树上出现。
解题思路:
Divide & Conquer + Global Variable(不需要 ResultType)
这题和 LCA 原题的区别主要是要找的 A 和 B 可能并不存在树里。所以我们要做出这两个改变
- 用全局变量把 A 和 B 是否找到保存起来。最后在 main function 里面要查看是否都找到
- 当 root 等于 A 或者 B 时不能直接返回root了。原题可以直接返回是因为两个 node 是保证存在的所以这情况下 LCA 一定是 root。
- 现在 root 等于 A 或者 B 我们还是要继续往下找是否存在另外的一个
不用 ResultType 的一个好处是:如果面试的时候出了一个原题,然后问这题做 follow up。如果从头开始写 result type 代码改动会比较大。一是比较容易写错,二是时间可能会不够。
这个方法只需要增加两个全局变量并且改动 LCA 原题的代码两行即可。
/**
* Definition of TreeNode:
* public class TreeNode {
* public int val;
* public TreeNode left, right;
* public TreeNode(int val) {
* this.val = val;
* this.left = this.right = null;
* }
* }
*/
public class Solution {
/*
* @param root: The root of the binary tree.
* @param A: A TreeNode
* @param B: A TreeNode
* @return: Return the LCA of the two nodes.
*/
public TreeNode lowestCommonAncestor3(TreeNode root, TreeNode A, TreeNode B) {
// write your code here
TreeNode res = helper(root, A, B);
// 程序执行完之后查看是否两个都找到
if(foundA && foundB)
return res;
else
return null;
}
private boolean foundA;
private boolean foundB;
private TreeNode helper(TreeNode root, TreeNode A, TreeNode B){
if(root == null)
return root;
TreeNode leftNode = helper(root.left, A, B);
TreeNode rightNode = helper(root.right, A, B);
// 如果 root 是要找的,更新全局变量
if(root == A || root == B){
foundA = (root == A) || foundA;
foundB = (root == B) || foundB;
return root;
}
// 和 LCA 原题的思路一样
if(rightNode != null && leftNode != null)
return root;
if(rightNode != null)
return rightNode;
if(leftNode != null)
return leftNode;
return null;
}
}