二叉树中两个节点的最近公共节点

一。后序遍历

1.如果本节点为空或者为c1/c2,则返回本节点

2.后序遍历

3.如果两个子树传的值都不为空,则返回本节点(说明找到了两个目标节点)

4.如果有一个节点为空,则另一个为空的可能是目标节点或者已经找到的公共祖先,此时则上传该值即可。


//
//  main.cpp
//  二叉树中两个节点的最近公共节点
//
//  Created by zjl on 16/9/17.
//  Copyright © 2016年 zjl. All rights reserved.
//

#include <iostream>
#include <vector>
#include <queue>
using namespace std;

struct TreeNode{
    int val;
    TreeNode* left;
    TreeNode* right;
    TreeNode(int x):val(x),left(NULL),right(NULL){}
};

TreeNode* create(vector<int>vec){
    int num = vec.size();
    TreeNode* root = new TreeNode(vec[0]);
    queue<TreeNode*> q;
    q.push(root);
    int i = 1;
    while(i <= num){
        TreeNode* t = q.front();
        q.pop();
        if(vec[i] > 0){
            t->left = new TreeNode(vec[i]);
            q.push(t->left);
        }
        else
            t->left = NULL;
        i++;
        if(i<= num){
            if(vec[i] > 0){
                t->right = new TreeNode(vec[i]);
                q.push(t->right);
            }
            else
                t->right = NULL;
            i++;
            
        }
    }
    return root;
}


TreeNode* solve(TreeNode* root, TreeNode* r1, TreeNode* r2){
    if(root == NULL || root == r1 || root == r2)
        return root;
    TreeNode* left = solve(root->left, r1, r2);
    TreeNode* right = solve(root->right, r1, r2);
    if(left != NULL && right != NULL)
        return root;
    return left != NULL ? left : right;
}

int main(int argc, const char * argv[]) {
    // insert code here...
    vector<int>num={1,2,3};
    TreeNode* root = create(num);
    TreeNode* c1 = new TreeNode(2);
    TreeNode* c2 = new TreeNode(3);
    TreeNode* res = solve(root, root->left,root->right);
    cout<< res->val <<endl;
    return 0;
}



二、用数组存储信息,以便多次查询 时间复杂度O(N)  空间复杂度O(N )  查找的时间复杂度为O(h) h为树的高度

过程:

1.为每个节点和其父节点建立映射

2.对目标节点1,对其的一条路径放到set中,然后对目标节点2在这集合中进行查找,如果没找到,就对节点2的父节点在这集合中找,直到找到为止


//
//  main.cpp
//  二叉树中两个节点的最近公共节点2
//
//  Created by zjl on 16/9/17.
//  Copyright © 2016年 zjl. All rights reserved.
//  用数组记录信息

#include <iostream>
#include <vector>
#include <queue>
#include <map>
#include <set>
using namespace std;

struct TreeNode{
    int val;
    TreeNode* left;
    TreeNode* right;
    TreeNode(int x):val(x),left(NULL),right(NULL){}
};
map<TreeNode*, TreeNode*>mp;

TreeNode* create(vector<int>vec){
    int num = vec.size();
    TreeNode* root = new TreeNode(vec[0]);
    queue<TreeNode*> q;
    q.push(root);
    int i = 1;
    while(i <= num){
        TreeNode* t = q.front();
        q.pop();
        if(vec[i] > 0){
            t->left = new TreeNode(vec[i]);
            q.push(t->left);
        }
        else
            t->left = NULL;
        i++;
        if(i<= num){
            if(vec[i] > 0){
                t->right = new TreeNode(vec[i]);
                q.push(t->right);
            }
            else
                t->right = NULL;
            i++;
            
        }
    }
    return root;
}

//set map value as <root, root's father>
void setmap(TreeNode* root){
    if(root == NULL) return;
    
    if(root->left != NULL)
        mp.insert(pair<TreeNode*, TreeNode*>(root->left, root));
    if(root->right != NULL)
        mp.insert(pair<TreeNode*, TreeNode*>(root->right, root));
    setmap(root->left);
    setmap(root->right);
    
}

//把c1的一整条路径放入set中,然后c2就在当中找,若没找到,则上升到c2的父节点找
TreeNode* search(TreeNode* c1, TreeNode* c2){
    set<TreeNode*>sets;
    while(mp.find(c1) != mp.end()){
        sets.insert(c1);
        c1 = mp[c1];
    }
    while(sets.find(c2) == sets.end()){
        c2 = mp[c2];
    }
    return c2;
}

TreeNode* solve(TreeNode* root, TreeNode* c1, TreeNode* c2){
    if(root != NULL) mp.insert(pair<TreeNode*, TreeNode*>(root, NULL));
    setmap(root); //先把每个节点找到其父节点
    return search(c1, c2);
}


int main(int argc, const char * argv[]) {
    // insert code here...
    vector<int>num={1,2,3};
    TreeNode* root = create(num);
    TreeNode* res = solve(root, root->left,root->right);
    cout<< res->val <<endl;
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值