算法提高:树型动态规划(二叉树找到两个节点的最近公共祖先)

二叉树找到两个节点的最近公共祖先

题目

给定一棵二叉树(保证非空)以及这棵树上的两个节点对应的val值 o1 和 o2,请找到 o1 和 o2 的最近公共祖先节点。
数据范围:树上节点数满足1≤n≤10^5, 节点值val满足区间 [0,n)
要求:时间复杂度O(n)
注:本题保证二叉树中每个节点的val值均不相同。


思路

这个题目是一个典型的树型动态规划,二叉树绝大多数的难题都是动态规划,比如说判断最大的线索二叉树(LeetCode——654),比如找到树上最远距离,本质上都是动态规划

按照动态规划的思路,就是把一个很大规模的问题,变成一个一个的小规模相同类型的问题,然后把结果进行逻辑处理,步步上传。

这个题目中找最近的公共祖先按照动态规划的思维去拆分就是:

  1. 先在左、右子树中找看是否存在最近祖先,是否存在A、是否存在B;
  2. 然后一直遍历左右子树,直到按照 后序遍历的方式把整个树遍历完;
  3. 遍历的过程中如果某个子树存在最近祖先,就把这个节点带上;
  4. 最后遍历完就得到了最终的最近祖先了;

代码

#include <iostream>
#include <string>
using namespace std;

class Tree {
public :
    char value;
    Tree* r;
    Tree* l;
};


class Res {
public:
    char ans_; // 最近的公共祖先
    bool isA_;
    bool isB_;
    Res(char ans, bool isA, bool isB):ans_(ans),isA_(isA),isB_(isB){}
    Res(){}
};

char A = 'A';
char B = 'B';
class solution {
public:
    void function(Tree*root) {
        if(!root) {
            //TODO: return nullptr
            cout <<"there is not ancestor" <<endl;
            return ;
        }
        Res res = prcess(root);
        if (res.ans_ != '') {
            cout << "nearst ancestor is " <<res.ans_ <<endl;
        }
    }

private:
    Res process(Tree*node) {
        if(!node) {
            return Res('',false,false);
        }
        Res res;
        res.ans_ = '';
        res.isA_ = false;
        res.isB_ = false;
        Res rl = process(node->l);
        Res rr = process(node->r);
        if (rl.ans_ != '') {
            res.ans_ = rl.ans_;
            res.isA_ = rl.isA_;
            res.isB_ = rl.isB_;
        }

        else if (rr.ans_ != '') {
            res.ans_ = rr.ans_;
            res.isA_ = rr.isA_;
            res.isB_ = rr.isB_;
        }

        else if (rl.isA_ || rr.isA_ || node->value == A) {
            res.isA_;
        }

        else (rl.isB_ || rr.isB_ || node->value == B) {
            res.isB_;
        }

        if(res.isA_ && res.isB_) {
            res.ans_ = node->value;
        }
      

        return res;
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ym影子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值