思路1:分别记录根节点到p和q的路径,两条路径中最后一个相同的节点就是共同祖先
思路2:若 root 是 p,q 的 最近公共祖先 ,则只可能为以下情况之一:
1.p 和 q 在 root 的子树中,且分列 root 的 异侧(即分别在左、右子树中)
2.p=root,且 q 在 root 的左或右子树中
3.q=root,且 p 在 root 的左或右子树中
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
List<TreeNode> path1 = getPath(root, p);
List<TreeNode> path2 = getPath(root, q);
TreeNode ancestor = null;
// 两条路径中最后一个相同的节点就是共同祖先
for (int i = 0; i < path1.size() && i < path2.size(); i++) {
if (path1.get(i) == path2.get(i)) {
ancestor = path1.get(i);
} else {
break;
}
}
return ancestor;
}
public List<TreeNode> getPath(TreeNode root, TreeNode target) {
TreeNode node = root;
List<TreeNode> path = new ArrayList<>();
while (node != target) {
path.add(node);
if (target.val < node.val) { // target在node的左子树
node = node.left;
} else if (target.val > node.val) { // target在node的右子树
node = node.right;
} else { // target == node跳出
break;
}
}
path.add(node); // 把target加入路径中
return path;
}
public TreeNode lowestCommonAncestor2(TreeNode root, TreeNode p, TreeNode q) {
TreeNode ancestor = root;
while (true) {
if (p.val < ancestor.val && q.val < ancestor.val) { //p q 都在左子树
ancestor = ancestor.left;
} else if (p.val > ancestor.val && q.val > ancestor.val) { //p q 都在右子树
ancestor = ancestor.right;
} else {
break;
}
}
return ancestor;
}
优化:保证 p.val<q.val
,则在循环中可减少判断条件。
public TreeNode lowestCommonAncestor4(TreeNode root, TreeNode p, TreeNode q) {
TreeNode ancestor = root;
if (p.val > q.val) { // 使 p.val < q.val
TreeNode tmp = p;
p = q;
q = tmp;
}
while (true) {
if (q.val < ancestor.val) { // 大的值 < ancestor.val 在左子树
ancestor = ancestor.left;
} else if (p.val > ancestor.val) { // 小的值 > ancestor.val 在右子树
ancestor = ancestor.right;
} else {
break;
}
}
return ancestor;
}
递归
public TreeNode lowestCommonAncestor3(TreeNode root, TreeNode p, TreeNode q) {
TreeNode ancestor = root;
if (p.val < ancestor.val && q.val < ancestor.val) {
return lowestCommonAncestor3(ancestor.left, p, q);
}
if (p.val > ancestor.val && q.val > ancestor.val) {
return lowestCommonAncestor3(ancestor.right, p, q);
}
return ancestor;
}