leetcode--Lowest Common Ancestor of a Binary Tree

本文介绍两种查找二叉树中两节点的最近公共祖先(LCA)的方法:递归后序遍历与非递归后序遍历并记录路径。通过实例详细解释了每种方法的具体实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Given a binary tree, find the lowest common ancestor (LCA) of two given nodes in the tree.

According to the definition of LCA on Wikipedia: “The lowest common ancestor is defined between two nodes v and w as the lowest node in T that has both v and w as descendants (where we allow a node to be a descendant of itself).”

        _______3______
       /              \
    ___5__          ___1__
   /      \        /      \
   6      _2       0       8
         /  \
         7   4

For example, the lowest common ancestor (LCA) of nodes 5 and 1 is 3. Another example is LCA of nodes 5 and 4 is 5, since a node can be a descendant of itself according to the LCA definition.


题意:给定一棵二叉树,查找两个节点的最接近的共同祖先LCA

分类:二叉树


解法1:要找到共同祖先,由于不是BST树,没有大小关系存在。但是我们可以想到后序遍历,对于后序遍历,是先遍历左子树,再右子树,最后是当前节点。

假设要找的是p,q两个节点的共同祖先,对于root节点,我们假设有一个函数

p,q都在左子树,那么应该在左子树找到p和q,而右子树则两者都找不到,这是我们可以判断共同祖先在左子树,递归查找。

如果p,q都在右子树,同样道理,左子树一个都找不到,那么我们递归在右子树里面找。

如果p,q在root的两侧,那么左子树和右子树都应该有返回值,这是root就是最近共同祖先。


并且这里有一个技巧,就是不必p,q都找到,例如在递归左子树的时候,先找到了p,我们就可以直接去右子树找,如果右子树没有找到q,意味着q在左子树

[java]  view plain  copy
  1. /** 
  2.  * Definition for a binary tree node. 
  3.  * public class TreeNode { 
  4.  *     int val; 
  5.  *     TreeNode left; 
  6.  *     TreeNode right; 
  7.  *     TreeNode(int x) { val = x; } 
  8.  * } 
  9.  */  
  10. public class Solution {  
  11.     public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {  
  12.         if (root == p || root == q || root == null) { return root; }//如果已经找到p,q返回,或者root为null,返回null  
  13.         TreeNode left = lowestCommonAncestor(root.left, p, q);//先在左子树找  
  14.         TreeNode right = lowestCommonAncestor(root.right, p, q);//再找右子树  
  15.         if(left != null && right != null){//如果左右子树分别有一个,则返回根节点  
  16.             return root;  
  17.         }else if(left!=null){//如果只在左子树,返回left  
  18.             return left;  
  19.         }else{//如果只在右子树,返回right  
  20.             return right;  
  21.         }  
  22.     }  
  23. }  

解法2:同样是后序遍历,使用后序遍历非递归算法一边遍历一边存储路径,找到p,q并且把它们的路径分别存储起来

最后比较这两条路径,找到最后一个相同的节点,则为所求

[java]  view plain  copy
  1. /** 
  2.  * Definition for a binary tree node. 
  3.  * public class TreeNode { 
  4.  *     int val; 
  5.  *     TreeNode left; 
  6.  *     TreeNode right; 
  7.  *     TreeNode(int x) { val = x; } 
  8.  * } 
  9.  */  
  10. public class Solution {  
  11.     public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {  
  12.         Stack<TreeNode> stack = new Stack<TreeNode>();  
  13.         ArrayList<TreeNode> path1 = new ArrayList<TreeNode>();  
  14.         ArrayList<TreeNode> path2 = new ArrayList<TreeNode>();  
  15.         int found = 0;//当前路径标志  
  16.         TreeNode cur = root;  
  17.         do{  
  18.             if(found==2break;  
  19.             while(cur!=null){  
  20.                 stack.add(cur);                  
  21.                 cur = cur.left;  
  22.             }  
  23.             TreeNode t = null;  
  24.             boolean flag = false;  
  25.             while(stack.size()>0&&!flag){  
  26.                 cur = stack.peek();                                  
  27.                 if(cur.right==t){//如果这个节点右节点为null或者右节点已经访问过  
  28.                     if(cur==p||cur==q){//判断是不是p,q,如果是就保存当前路径  
  29.                         if(found==0) path1.addAll(stack);  
  30.                         else path2.addAll(stack);  
  31.                         found++;  
  32.                     }  
  33.                     stack.pop();  
  34.                     t = cur;  
  35.                 }else{//如果右节点没有被访问过,先遍历右子树  
  36.                     flag = true;  
  37.                     cur = cur.right;  
  38.                 }  
  39.             }  
  40.         }while(stack.size()>0);  
  41.         int i = 0;  
  42.         while(i<path1.size()&&i<path2.size()){//从头开始查找最后一个相同的节点  
  43.             if(path1.get(i)!=path2.get(i)) break;  
  44.             else i++;  
  45.         }  
  46.         return path1.get(i-1);  
  47.     }  
  48. }  

原文链接http://blog.youkuaiyun.com/crazy__chen/article/details/47185439

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值