天天看點

在二叉樹中找到兩個結點的最近公共祖先(LCA) Apare_xzc在二叉樹中找到兩個結點的最近公共祖先(LCA)

在二叉樹中找到兩個結點的最近公共祖先(LCA)

牛客題目連結<–

樹的結點定義:

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

題意:

給定一顆二叉樹的根結點,資料保證樹中每個結點的val值都不同。給兩個值O1, O2, 求O1所在結點 和 O2 所在結點 的最近公共祖先結點的val值。

函數接口要求:

/*
* struct TreeNode{
* 	int val;
* 	struct TreeNode * left;
* 	struct TreeNode * right;
*	TreeNode(int x=0) : val(x), left(NULL), right(NULL) {}
* }
*/
class Solution {
public:
    /**
     * 
     * @param root TreeNode類 
     * @param o1 int整型 
     * @param o2 int整型 
     * @return int整型
     */
    int lowestCommonAncestor(TreeNode* root,int o1,int o2) {
    	//write code here
	}
};
           

思路一:dfs找到所有O1的祖先結點,dfs找到所有O2的祖先結點,然後bfs層序周遊,找到最後一個即為O1祖先,有為O2祖先 的結點即為答案

class Solution {
public:
    /**
     * 
     * @param root TreeNode類 
     * @param o1 int整型 
     * @param o2 int整型 
     * @return int整型
     */
    void dfs(TreeNode * now,int val,unordered_map<TreeNode*,int>& mp) {
        if(!now) return;
        if(now->val==val) { //找到了這個值 
            mp[now] = 1;
            return;
        }
        if(now->left) {
            dfs(now->left,val,mp);
            auto it = mp.find(now->left);
            if(it!=mp.end()) { //說明在左子樹中 
                mp[now] = 1;
                return;
            }
        }
        if(now->right) {
            dfs(now->right,val,mp);
            auto it = mp.find(now->right);
            if(it!=mp.end()) {
                mp[now]=1;
            }
        }
    }                    
    int bfs(TreeNode * root,unordered_map<TreeNode*,int>&fo1,unordered_map<TreeNode*,int>&fo2) {
        if(!root) return -1; 
        queue<TreeNode*> Q;
        Q.push(root);
        int ans = -1;
        while(!Q.empty()) {
            TreeNode * tp = Q.front();
            Q.pop();
            if(fo1.find(tp)!=fo1.end() && fo2.find(tp)!=fo2.end()) ans = tp->val;
            if(tp->left) Q.push(tp->left);
            if(tp->right) Q.push(tp->right);
        }
        return ans;
    }
    int lowestCommonAncestor(TreeNode* root, int o1, int o2) {
        unordered_map<TreeNode*,int> fo1; //标記所有o1的祖先結點(包括它自己)
        unordered_map<TreeNode*,int> fo2; //标記所有o2的祖先結點(包括它自己)
        dfs(root,o1,fo1);
        dfs(root,o2,fo2);
        return bfs(root,fo1,fo2); 
    }
};
           

思路二:樸素倍增。找到o1的高度和o2的高度,先跳到高度一樣了,然後再一起一個一個往上跳,直到相遇

class Solution {
public:
    /**
     * 
     * @param root TreeNode類 
     * @param o1 int整型 
     * @param o2 int整型 
     * @return int整型
     */
    int lowestCommonAncestor(TreeNode* root,int o1,int o2) {
    	unordered_map<int,int> Height;
    	unordered_map<int,int> fa;
    	getFatherAndHeight(root,1,Height,fa);
    	int h1 = Height[o1], h2 = Height[o2];
    	while(h2>h1) o2 = fa[o2],--h2;
    	while(h2<h1) o1 = fa[o1],--h1;
		while(o2!=o1) o2 = fa[o2], o1 = fa[o1];
		return o1; 
	}
    void getFatherAndHeight(TreeNode * root,int h,unordered_map<int,int>&Height,unordered_map<int,int>& fa) {
    	if(!root) return;
    	Height[root->val] = h;
    	if(root->left) {
    		fa[root->left->val] = root->val;
    		getFatherAndHeight(root->left,h+1,Height,fa);
		}
		if(root->right) {
			fa[root->right->val] = root->val;
			getFatherAndHeight(root->right,h+1,Height,fa);
		}
	} 
};
           

思路三,遞歸

//201ms
class Solution {
public:
    /**
     * 
     * @param root TreeNode類 
     * @param o1 int整型 
     * @param o2 int整型 
     * @return int整型
     */
     
     TreeNode* dfs(TreeNode * root,int o1,int o2) {
         if(root==nullptr||root->val==o1||root->val==o2) return root;
         TreeNode * lans = dfs(root->left,o1,o2); 
         TreeNode * rans = dfs(root->right,o1,o2);
         if(lans==nullptr) return rans; //o1,o2都在右子樹
         if(rans==nullptr) return lans; //o1,o2都在左子樹
         return root; //o1,o2,左子樹右子樹各有一個
     }
     int lowestCommonAncestor(TreeNode* root,int o1,int o2) {
    	return dfs(root,o1,o2)->val; 
	}
 
};
           

自己調試代碼

/*struct TreeNode {
	int val;
	struct TreeNode *left;
	struct TreeNode *right;
	TreeNode(int x):val(x),left(NULL),right(NULL){}
	TreeNode():left(NULL),right(NULL){} 
};*/
vector<string> vstr = {"1","2","4","#","#","5","#","#","3","6","#","#","7","#","#"}; //先序建樹 
TreeNode * build(vector<string>& vstr,int& x) {
	if(vstr[x]==string("#")) {
		++x; return nullptr;		
	}  
	TreeNode * root = new TreeNode();
	istringstream ism(vstr[x++]);
	ism>>root->val;
	root->left = build(vstr,x);
	root->right = build(vstr,x);
	return root; 
}