二叉树的最近公共祖先--递归--回溯

二叉树的最近公共祖先--递归--回溯_第1张图片

 思路:

                如果能够自底向上查找元素,就能找到公共祖先了

                 回溯啊:回溯就是天然的自底向上查找元素。

                而后序遍历就是天然的回溯过程:因为后序遍历先处理的一定是叶子节点,

接下来就是逻辑处理过程,

1,如果一个节点的左为p(q),右为q(p),那这个节点一定是最近的祖先。

2,如果走到左树的节点(p)为null,而右树(q)找到节点,此时,祖先(q)一定为右节点,p在q的左右子树里面,q为最近祖先

3,如果两个节点都为空,说明没有公共祖先

递归三部曲:

 

1,确定递归函数返回值以及参数

        需要递归函数告诉我们,是否找到了这个节点,但我们最后要返回节点,所以需要返回找到的当前节点,如果返回值为null,说明没找到

TreeNode*left=lowestCommonAncestor(root->left,p,q);

2,确定终止条件

如果找到了节点p或者q或者走到nullptr,直接返回

if(root==p||root==q||root==nullptr)return root

3,确定递归单层逻辑

值得注意的是 本题函数有返回值,是因为回溯的过程需要递归函数的返回值做判断,但本题我们依然要遍历树的所有节点。

递归函数有返回值就是要遍历某一条边,但有返回值也要看如何处理返回值!

搜索一条边的写法

if(递归函数(root->left))return ;
if(递归函数(root->right))return ;

搜索一颗树的写法

left = 递归函数(root->left);
right = 递归函数(root->right);
left与right的逻辑处理;

在递归函数有返回值的情况下:如果要搜索一条边,递归函数返回值不为空的时候,立刻返回,如果搜索整个树,直接用一个变量left、right接住返回值,这个left、right后序还有逻辑处理的需要,也就是后序遍历中处理中间节点的逻辑(也是回溯)。

逻辑处理:

 //处理逻辑
        if(left!=nullptr&&right!=nullptr)return root;
        if(left==nullptr&&right!=nullptr)
        return right;
        else if(left!=nullptr&&right==nullptr)
        return left;
        else return nullptr;

代码:

class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) 
    {
        if(root==p||root==q||root==nullptr)return root;
        //递归查找左右节点
        TreeNode*left=lowestCommonAncestor(root->left,p,q);
        TreeNode*right=lowestCommonAncestor(root->right,p,q);
        //处理逻辑
        if(left!=nullptr&&right!=nullptr)return root;
        if(left==nullptr&&right!=nullptr)
        return right;
        else if(left!=nullptr&&right==nullptr)
        return left;
        else return nullptr;
    }
};

你可能感兴趣的:(算法集合,c++,回归算法,回溯)