【剑指offer-C++】JZ86:在二叉树中找到两个节点的最近公共祖先

【剑指offer-C++】JZ86:在二叉树中找到两个节点的最近公共祖先

    • 题目描述
    • 解题思路

题目描述

描述:给定一棵二叉树(保证非空)以及这棵树上的两个节点对应的val值 o1 和 o2,请找到 o1 和 o2 的最近公共祖先节点。

数据范围:树上节点数满足 , 节点值val满足区间 [0,n)。

要求:时间复杂度 O(n)。

注:本题保证二叉树中每个节点的val值均不相同。

如当输入{3,5,1,6,2,0,8,#,#,7,4},5,1时,二叉树{3,5,1,6,2,0,8,#,#,7,4}如下图所示:

【剑指offer-C++】JZ86:在二叉树中找到两个节点的最近公共祖先_第1张图片

所以节点值为5和节点值为1的节点的最近公共祖先节点的节点值为3,所以对应的输出为3。

节点本身可以视为自己的祖先。

输入:{3,5,1,6,2,0,8,#,#,7,4},5,1
返回值:3
输入:{3,5,1,6,2,0,8,#,#,7,4},2,7
返回值:2

解题思路

在二叉树中找到两个节点的最近公共祖先:最直观的想法是,数组存储法。首先遍历二叉树,分别找到从根节点到o1与从根节点到o2的路径数组,然后比较两个数组找到最后一个相同的元素即为o1和o2的最近公共祖先。在遍历二叉树的过程中,由于要找的是从根节点到某一节点的路径,故使用前序遍历。其与二叉搜索树的区别是,二叉搜索树的前序遍历的左和右部分都是满足条件再进入循环,而该普通二叉树中没有,故左边返回后可能还会进入右边,这时我们就需要加一个标记是否找到的全局变量flag,在递归终止条件中需要加上当找到即flag为true时则返回,在左右递归遍历结束后还需要判断flag是否为true,如果是则表明找到返回即可,否则表示没找到则要将当前元素弹出数组。

vector path1;
vector path2;
bool flag=false; // 标记是否找到
// 求解路径数组 
void dfs(TreeNode* root,int o,vector& path)
{
   if(flag||!root) return;  // 当为空或者已经找到则返回空
   path.push_back(root->val);
   if(root->val==o)
   {
       flag=true; // 标记找到 否则后续会继续遍历
       return;
   }
   dfs(root->left,o,path);
   dfs(root->right,o,path);
   // 找到
   if(flag)
     return;
   // 没找到弹出元素
   path.pop_back();
}
int lowestCommonAncestor(TreeNode* root, int o1, int o2) 
{
    dfs(root,o1,path1);
    flag=false; // 重置为空
    dfs(root,o2,path2);
    int res;
    // 记录最后一个相同的
    for(int i=0,j=0;i

idea:上述方法是先找到路径,再比较路径,其实可以边遍历边比较。如果节点为空则返回-1,如果当前节点是两者其中之一,则返回当前节点值,然后再依次遍历左子树和右子树,当左子树返回-1则表明在左子树没找到故返回右子树,反之当右子树返回-1则表明在右子树没找到故返回左子树,反之两个都找到了则表明最近公共祖先即为当前节点。

int lowestCommonAncestor(TreeNode* root, int o1, int o2) 
{
   // 该子树没找到返回-1
   if(root==NULL)
      return -1;
   // 该节点是其中某一个节点
   if(root->val==o1||root->val==o2)
      return root->val;
   // 左子树寻找祖先
   int left=lowestCommonAncestor(root->left, o1, o2);
   // 右子树寻找祖先
   int right=lowestCommonAncestor(root->right, o1, o2);
   // 左子树没找到则在右子树上
   if(left==-1)
      return right;
   // 右子树没找到则在左子树上
   if(right==-1)
      return left;
   // 否则是当前节点
   return root->val;
}

你可能感兴趣的:(剑指offer,c++,算法,深度优先)