leetcode 235 &236 树的最近公共祖先 medium

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/speargod/article/details/98784927

leetcode 235. 二叉搜索树的最近公共祖先  easy     

题目描述:

给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。

说明:

  • 所有节点的值都是唯一的。
  • p、q 为不同节点且均存在于给定的二叉搜索树中。

解题思路:

如果是二叉搜索树,可以从根节点开始和两个指定节点进行比较,假如当前节点的值比两个节点的值都大,那么最近公共祖先一定在左子树上,而假如当前节点的值比两个节点的值都小,那么最近公共祖先一定在右子树,否则就是当前节点的值,处于两个节点的值之间(或者,就是某个节点的值),那么最近公共祖先就是这个节点!

代码:

class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        if(!root || !p || !q)
            return nullptr;
        TreeNode *cur=root;
        while(cur){
            // 如果当前节点的值比两个节点的值都大,那么最近公共祖先一定在左子树
            if(cur->val > p->val && cur->val >q->val) cur=cur->left; 
            
            //如果当前节点的值比两个节点的值都小,那么最近公共祖先一定在右子树
            else if(cur->val < p->val && cur->val < q->val) cur=cur->right;
            else return cur;
        }
        
        return nullptr;
        
    }
};

leetcode 236. 二叉树的最近公共祖先  medium          

题目描述:

给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。

说明:

  • 所有节点的值都是唯一的。
  • p、q 为不同节点且均存在于给定的二叉树中。

解题思路:

方法1: 递归

因为题目说明p,q肯定在给定的二叉树中,所以我们的函数实现的功能可以不只是返回两个节点的最近公共祖先。

而是:

1)假如以当前节点为根的子树中存在p,q的最近公共祖先,返回这个祖先。

2)假如不存在,但是存在p或q中的任意一个,返回p或者q。

3)假如都不存在,返回nullptr

具体实现是在递归函数中,首先看当前结点是否为空,若为空则直接返回空,若为p或q中的任意一个,也直接返回当前结点。否则的话就对其左右子结点分别调用递归函数,由于这道题限制了p和q一定都在二叉树中存在,那么如果当前结点不等于p或q,p和q要么分别位于左右子树中,要么同时位于左子树,或者同时位于右子树,那么我们分别来讨论:

- 若p和q分别位于左右子树中,那么对左右子结点调用递归函数,会分别返回p和q结点的位置,而当前结点正好就是p和q的最小共同父结点,直接返回当前结点即可,这就是题目中的例子1的情况。

- 若p和q同时位于左子树,这里有两种情况,一种情况是 left 会返回p和q中较高的那个位置,而 right 会返回空,所以最终返回非空的 left 即可,这就是题目中的例子2的情况。还有一种情况是会返回p和q的最小父结点,就是说当前结点的左子树中的某个结点才是p和q的最小父结点,会被返回。

- 若p和q同时位于右子树,同样这里有两种情况,一种情况是 right 会返回p和q中较高的那个位置,而 left 会返回空,所以最终返回非空的 right 即可,还有一种情况是会返回p和q的最小父结点,就是说当前结点的右子树中的某个结点才是p和q的最小父结点,会被返回。

(当然在局部递归的时候,存在left和right都为nullptr的时候,这时候返回nullptr即可)

  但是这种方法只适合p,q均在树上。比如节点p不在,而节点q在的话,下面的函数会返回节点q,但是应该要返回nullptr。 所以假如题目没提p,q是否在树上,那要先检查p,q是否都在树上(很简单的递归函数)。假如至少有一个不在,直接返回nullptr

代码:

class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        //这种方法只适合p,q均在树上。
        //假如可能节点不在的话,那要先检查p,q是否都在树上(很简单的递归函数)。
        //假如至少有一个不在,直接返回nullptr
        
        if(root==nullptr || p==root || q==root) //如果p==root或者q==root,说明找到了p和q
            return root;
        
        //找左子树中是否存在p或q,存在时返回p或q或者p,q的祖先结点,不存在时返回nullptr
        TreeNode *left=lowestCommonAncestor(root->left,p,q); 
        TreeNode *right=lowestCommonAncestor(root->right,p,q);   //找右子树中是否存在p或q
        
        //left和right分别有p或q,则root为p,q的最低公共祖先
        if(left && right)
            return root;
        
        //哪个非空,返回哪个(假如都空,返回nullptr,也对)
        return left?left:right; 
        
    }
};

another方法:

剑指offer上的,具体代码就不写了

用dfs分别找到根节点到p 和 q 结点的路径,然后找到他们两个路径上最后一个相等的节点即可(不止适用于2叉树,n叉树也可以)

猜你喜欢

转载自blog.csdn.net/speargod/article/details/98784927