LeetCode:(236. 二叉树的最近公共祖先)

题目

题目链接

LeetCode:(236. 二叉树的最近公共祖先)_第1张图片
思路1:
该方法比较巧妙,就是如果p,q在一个结点的两边,那么他就是最近的公共祖先。使用这个思路,就是找这个结点是不是在左右两边。
如果pq都在左边/右边,就再去左/右子树去寻找,直到pq分别在左右子树即可。

LeetCode:(236. 二叉树的最近公共祖先)_第2张图片

class Solution {
public:
// 找x在没在该树下面,在返回true,不再返回false
    bool IsInTree(TreeNode* root, TreeNode* x) 
    {
        if(root == nullptr)
        {
            return false;
        }
        //注意该返回方式,很巧妙,找到就结束了。
        return root == x
        || IsInTree(root->left, x)
        || IsInTree(root->right, x);
    }
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        
        if(root == nullptr)
        {
            return nullptr;
        }
        //只要有一个结点是root,该结点必是祖先
        if(p == root || q == root)
        {
            return root;   //这是出口1
        }

        //根不是,这种方法也很巧妙,看是否在左边,不再就在右边。
        bool pLeft = IsInTree(root->left,p);
        bool pRight = !pLeft;

        bool qLeft = IsInTree(root->left, q);
        bool qRight = !qLeft;

        if((pLeft && qRight) || (pRight && qLeft))
        {
            return root;    //这是出口2
        }
        else if(pLeft&&qLeft)  //都在左边
        {
            return lowestCommonAncestor(root->left, p, q);    //去找出口,找到直接结束了
        }
        else      //都在右边
        {
            return lowestCommonAncestor(root->right, p, q);
        }
    }
};

难点:虽然思路很清晰,但是考验代码和递归的控制能力。(找到该节点就不再递归了,应该立马结束,应该怎么控制?可以有||,可以直接return)
好好理解,希望能举一反三!!!

思路2:
分别找到p,q两个结点的路径,当成链表相交问题。长链表先走差距步,然后再一块走。地址相同结点即为祖先结点。

class Solution {
public:
bool GetPath(TreeNode* root, stack<TreeNode*>& path, TreeNode* x)
{
    if(root == nullptr)
    {
        return false;
    }
    path.push(root);
    if(root == x)
    {
        return true;
    }
    if(GetPath(root->left, path, x))
    {
        return true;
    }
    if(GetPath(root->right, path, x))
    {
        return true;
    }
    path.pop();
    return false;
}   

    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        stack<TreeNode*> pPath;
        stack<TreeNode*> qPath;
        GetPath(root, pPath, p);        
        GetPath(root, qPath, q);
        while(pPath.size()!=qPath.size())
        {
            if(pPath.size()>qPath.size())
            {
                pPath.pop();
            }
            else
            {
                qPath.pop();
            }
        }
        while(pPath.top()!=qPath.top())
        {
            pPath.pop();
            qPath.pop();
        }
        return qPath.top();
    }
};

难点:

  1. 递归去找结点的路径,这个方法也很巧妙,注意揣摩。

你可能感兴趣的:(算法题,C++,leetcode,算法,职场和发展)