题目描述
方法一:分治法(递归)
分治法的思想就是在每一层分为左右子树进行寻找,左右子树返回的leftNode和rightNode如果都不为空,则说明A和B在左右子树各有一个,则返回当前节点;如果leftNode和rightNode有一个为空一个不为空,则有两种情况,第一种情况就是A和B都是一边子树,另一边子树两个节点都没找到,第二种情况就是A或者B中的某一个在某一子树,而另外一个子树中两个节点都没找到,为了区分这两种情况,我们使用foundA和foundB来记录两个节点是否被找到的状态。
Java代码实现
boolean foundA, foundB;
public TreeNode lowestCommonAncestor3(TreeNode root, TreeNode A, TreeNode B) {
TreeNode treeNode = divConq(root, A, B);
if (foundA && foundB)
return treeNode;
return null;
}
public TreeNode divConq(TreeNode root, TreeNode A, TreeNode B) {
if (root == null)
return root;
TreeNode leftNode = divConq(root.left, A, B);
TreeNode rightNode = divConq(root.right, A, B);
if (root == A) {
foundA |= true;
return root;
}
if (root == B) {
foundB |= true;
return root;
}
if (leftNode != null && rightNode != null)
return root;
if (leftNode != null)
return leftNode;
if (rightNode != null)
return rightNode;
return null;
}
方法二:非递归法
思路很简单:
- 遍历树,一边遍历一边向哈希表里面添加<子,父>键值对
- 从节点A出发到root,将沿途的祖先节点放到一个列表list中
- 从节点B出发向root遍历,第一次遇到列表list中存在的节点即为最近公共祖先
Java代码实现
public TreeNode lowestCommonAncestor3(TreeNode root, TreeNode p, TreeNode q) {
HashMap<TreeNode, TreeNode> map = new HashMap<>();
Stack<TreeNode> s = new Stack();
List<TreeNode> list = new ArrayList<>();
TreeNode top;
if (root == null)
return root;
s.push(root);
map.put(root, null);
while (!map.containsKey(p) || !map.containsKey(q)) {
if(s.empty())
break;
top = s.pop();
if (top.left != null) {
s.push(top.left);
map.put(top.left, top);
}
if (top.right != null) {
s.push(top.right);
map.put(top.right, top);
}
}
TreeNode t = p;
while (t != null) {
list.add(t);
t = map.get(t);
}
t = q;
while (t != null) {
if (list.contains(t))
break;
t = map.get(t);
}
return t;
}