二叉树路径问题【寻找最近公共祖先(lca)】

题目见力扣270场周赛第三题从二叉树一个节点到另一个节点每一步的方向
在这里插入图片描述
很明显这个题需要我们求解两个节点的最近公共祖先,这样才是最短路径,在求得他们的最近公共祖先后,从这个结点T到出发结点startValue的路径记录在ans1中,从T到目的结点destValue的路径记录在ans2中,我们可以很明显的发现最后的答案就是将ans1中的‘L’和‘R’全部转换成‘U’,然后拼接在ans2之前,就是整个的最短路径。
在求解最近公共祖先时,我们可以采用以下方法:从头节点出发,到起始结点s的路径记录在ans1中,从头节点出发,到目的结点的路径记录在ans2中,那么最近的公共祖先就是两个记录中出现的第一个不同的数字的前一个结点,即最后一个出现的相同的字符。例如:

假设ans1中记录了”LLRL“,ans2中记录了”LRR“,那么,两个结点的最近公共祖先就是头结点的‘L’结点,即头节点的左孩子结点。

同时,因为我们已经遍历从头节点遍历过一次了,必然经过了最近公共祖先,因此不需要从最近公共祖先处再次遍历,只需要删除前面相同的字符然后按照规则拼接即可,例如

对于前一个例子,我们删除相同的字符L,此时ans1中记录了”LRL“,ans2中记录了”RR“,将ans1中的字符换成‘U’,得到ans1中记录为:“UUU”,把ans2拼接在ans1之后,得到最终的ans为:“UUURR”。

代码如下,有部分修改:

bool find(TreeNode* root,int x,vector<char>&ans){
    if(root->val==x) return true;
    if(root->left){
        ans.push_back('L');
        if(find(root->left,x,ans)) return true;  //如果找到的话就直接返回,就不pop了
        ans.pop_back();
    }
    if(root->right){
        ans.push_back('R');
        if(find(root->right,x,ans)) return true;
        ans.pop_back();
    }
    return false;
}
string getDirections(TreeNode* root, int startValue, int destValue) {
    vector<char>ans1;
    vector<char>ans2;
    string s="";
    find(root,startValue,ans1);
    find(root,destValue,ans2);
    int n=ans1.size();
    int m=ans2.size();
    int pos=0;
    while(n&&m&&pos<n&&pos<m){
        if(ans1[pos]==ans2[pos]){
            ans1[pos]=' ';
            ans2[pos]=' ';
        }
        else break;
        pos++;
    }
    for(int i=0;i<n;i++){
        if(ans1[i]=='L'||ans1[i]=='R') s+="U";
    }
    for(int i=0;i<m;i++){
        if(ans2[i]!=' ') {
            s+=string(1,ans2[i]);
        }
    }
    return s;
}

事实上也可以用图论的方法做,同时,寻找最近公共祖先也有多种方法P236二叉树的最近公共祖先,见博客二叉树的最近公共祖先

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值