- 题目链接: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; } };
- 方法一:递归