尋找二叉樹的最近公共祖先
這道題在面試過程遇到了兩次了,感覺是一個高頻考點,特此總結一下
解題思路:
祖先定義: 若節點p 在節點root 的左子樹或者右子樹中,則稱root是p的祖先
最近公共祖先的定義: 設節點root 為節點p,q的最近公共祖先,若其左子節點root.left,和右子節點
root.right 都不是p,q的公共祖先在,則稱root 是最近的公共祖先
根據以上定義,若root是p,q的最近公共祖先,則只可能為以下情況之一:
1,p和q在root的子樹中,且分列root的兩側,即分別為左右子樹中。
2, p = root ,且q 在root 的左或右子樹中
3,q = root,且 p 在root 的左或者右子樹中
考慮通過遞迴對二叉樹進行後續遍歷,當遇到節點p 或者q 時返回,從底至頂回溯,當節點p ,q,在節點root兩側時,即為最近公共祖先,則向上返回root
遞迴解析
1,終止條件:
1,當越過葉子節點,則直接返回Null
2,當root 等於p ,q,則直接返回root
2.遞推工作
1,開啟遞迴左子節點,返回值記為left
2, 開啟遞迴右子節點,返回值記為right
3, 返回值
1,當left 和right 同時為空,說明,root 的左/右子樹中都不包含p,q. 返回Null
2, 當left 和right 同時不為空,說明,p,q,分別在root的兩側,因此root為最近的公共祖先,返回root
3, 當left 為空,right 不為空: p,q 都不在root 的左子樹中,直接返回right,具體可分為兩種情況:
-
p,q, 其中一個在root 的右子樹中,p 或者q 就是root 的右子樹, 此時right 指向 p(假設為p )
-
p,q,兩個基點都在root的右子樹中,此時的right 指向最近的公共祖先節點
4,當left 不為空,right 為空,直接返回left ,與3 同理
public static TreeNode lowestCommonAncestor (TreeNode root ,TreeNode p,TreeNoe q ){
if(root==null || 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 null;}
if(left == null ){return right; }
if(right == null ){return left; }
return root;
}
驗證:
import java.util.*;
public class TreeExercise1 {
public static void main(String[] args ){
TreeNode p3 = new TreeNode(3);
TreeNode p5 = new TreeNode(5);
TreeNode p1 = new TreeNode(1);
TreeNode p6 = new TreeNode(6);
TreeNode p2 = new TreeNode(2);
TreeNode p0 = new TreeNode(0);
TreeNode p8 = new TreeNode(8);
TreeNode p7 = new TreeNode(7);
TreeNode p4 = new TreeNode(4);
p3.left = p5;
p3.right = p1;
p5.left = p6;
p5.right = p2;
p1.left = p0;
p1.right = p8;
p2.left = p7;
p2.right = p4;
// inorferFix(p3);
TreeNode res = lowestCommonAncestor(p3,p2,p6);
inorderFix(res);
}
public static TreeNode lowestCommonAncestor(TreeNode root,TreeNode p,TreeNode q ){
if(root==null || 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 null; }
if(left == null ){return right; }
if(right == null ){return left ; }
return root;
}
private static void inorferFix(TreeNode root ){
if(root==null ){
return;
}
if(root.left != null ){
inorferFix(root.left);
}
System.