题目:
分析:此题可以采用递归的方法做,也可以采用非递归的基于链表和栈的方法来做。
方法一:当遍历到一个root点的时候:
- 判断root是不是null,如果root为null或者root为所要找的结点,那么直接返回root即可。
- 如果root的左子树存在p,右子树存在q,则root就肯定是最近祖先
- 如果p、q都在root的左子树,那么就递归root的左子树,右子树同理
//递归
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode A, TreeNode B) {
// write your code here
if(root==null || root==A || root==B) return root;
TreeNode FindLeft=lowestCommonAncestor(root.left,A,B);
TreeNode FindRight=lowestCommonAncestor(root.right,A,B);
if(FindLeft!=null && FindRight!=null){
return root;
}else{
return FindLeft==null?FindRight:FindLeft;
}
}
方法二:非递归,基于链表
//非递归,基于链表
public TreeNode lowestCommonAncestor1(TreeNode root, TreeNode A, TreeNode B) {
if(root==null || root==A || root==B) return root;
ArrayList<TreeNode> l1=new ArrayList<>();
ArrayList<TreeNode> l2=new ArrayList<>();
FindPath(root,A,l1);
FindPath(root,B,l2);
TreeNode result=root;
for(int i=0;i<l1.size() && i<l2.size();i++){
if(l1.get(i)==l2.get(i)){
result=l1.get(i);
}else{
break;
}
}
return result;
}
private boolean FindPath(TreeNode root, TreeNode target, ArrayList<TreeNode> arr){
if(root==null) return false;
arr.add(root);
if(root==target) return true;
if(FindPath(root.left,target,arr) || FindPath(root.right,target,arr))
return true;
//没找到,把之前添加到链表中的结点删除
arr.remove(arr.size()-1);
return false;
}
方法三:非递归,基于栈
//非递归,用栈
public TreeNode lowestCommonAncestor2(TreeNode root, TreeNode A, TreeNode B) {
if(root==null || root==A || root==B) return root;
Stack<TreeNode> s1=new Stack<>();
Stack<TreeNode> s2=new Stack<>();
TreeNode result=root;
if(FindPath1(root,A,s1) && FindPath1(root,B,s2)){
while(!s1.isEmpty()){
TreeNode node=s1.pop();
if(s2.contains(node)){
result=node;
}
}
}
return result;
}
private boolean FindPath1(TreeNode root,TreeNode target,Stack<TreeNode> stack){
if(root==null) return false;
if(root==target){
stack.push(root);
return true;
}
if(FindPath1(root.left,target,stack) || FindPath1(root.right,target,stack)){
stack.push(root);
return true;
}
return false;
}