0
点赞
收藏
分享

微信扫一扫

236. 二叉树的最近公共祖先(二叉树+遍历)

瑾谋 2022-04-24 阅读 75
算法c++
  • 题目链接:236. 二叉树的最近公共祖先
  • 考查知识:二叉树+遍历
  • 题意描述:给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。
  • 具体代码
    • 方法一:递归
      • 采用后序遍历,递归到叶结点向上访问时,函数返回值是判断当前结点子树是否包含p或q
      • 不断判断当前结点的左右子树分别包含pq 或 当前结点包含p/q且左/右子树包含另一个,则ans记录最近公共祖先
        class Solution {
        	TreeNode *ans;
        public:
        	bool dfs(TreeNode *root,TreeNode *p,TreeNode* q){
        		if(root==NULL)return false;//递归边界 
        		bool left=dfs(root->left,p,q),right=dfs(root->right,p,q);//递归左右子树,后序遍历 
        		if((left&&right)||(root->val==p->val||root->val==q->val)&&(left||right))ans=root;//左右子树分别包含pq 或 当前结点包含p/q且左/右子树包含q/p 
        		return left||right||(root->val==p->val||root->val==q->val);//当前结点子树是否包含p或q 
        	}
            TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
                 dfs(root,p,q);
                 return ans;
            }
        };
        
    • 方法二:哈希
      • 用哈希表存储所有节点的父节点,就可以实现类似三叉链表对一个结点的父结点、左右孩子进行访问
      • 具体实现是递归访问所有结点,并用map记录孩子结点到父结点的映射
      • 然后从p结点访问到根结点并将沿途的结点标记为已访问,从q结点访问到根结点并将沿途的结点标记为已访问,第一个路径重合的结点即最近公共祖先
        class Solution {
        	unordered_map<TreeNode*,TreeNode*>fa;//孩子结点,父结点 
        	unordered_map<TreeNode*,int>vis;//该结点,是否被遍历过 
        public:
        	void dfs(TreeNode *root){//递归访问所有结点,并用map记录孩子结点到父结点的映射 
        		if(root->left!=NULL){
        			fa[root->left]=root;
        			dfs(root->left);
        		}
        		if(root->right!=NULL){
        			fa[root->right]=root;
        			dfs(root->right);
        		}
        	}
            TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
                fa[root]=NULL;
                dfs(root);
                while(p!=NULL){//从p结点访问到根结点,并将沿途的结点标记为已访问 
                	vis[p]=1;
                	p=fa[p];
        		}
        		while(q!=NULL){//从q结点访问到根结点,并将沿途的结点标记为已访问 
        			if(vis[q])return q;//第一个路径重合的结点即最近公共祖先 
        			q=fa[q]; 
        		}
        		return NULL;
            }
        };
        
举报

相关推荐

0 条评论