给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
例如,给定如下二叉树: root = [3,5,1,6,2,0,8,null,null,7,4]
示例 1:
输入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
输出: 3
解释: 节点 5 和节点 1 的最近公共祖先是节点 3。
示例 2:
输入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4
输出: 5
解释: 节点 5 和节点 4 的最近公共祖先是节点 5。因为根据定义最近公共祖先节点可以为节点本身。
说明:
所有节点的值都是唯一的。
p、q 为不同节点且均存在于给定的二叉树中。
code1:
左右子树的近公共结点可以是左右子树其中任何一结点,也可是其最近公共根节点
应该采用后序遍历,因为只有找到p、q后,才可以找其最近公共祖先结点,而在二叉排序树中找其最近公共祖先结点时,因为已经有结点的大小关系,所以可以用先序遍历根据结点的大小关系来判断
/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */ class Solution { public: TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) { if(!root||!p||!q) return nullptr; TreeNode* resNode=nullptr; lowestCommonAncestorCore(root,p,q,resNode); return resNode; } private: int lowestCommonAncestorCore(TreeNode* curNode,TreeNode* p,TreeNode* q,TreeNode* &resNode) { if(!curNode) return 0; int left=lowestCommonAncestorCore(curNode->left,p,q,resNode); int right=lowestCommonAncestorCore(curNode->right,p,q,resNode); int cur=(curNode==p||curNode==q)?1:0; if(left+right+cur>=2) resNode=curNode; return left||right||cur?1:0; } };
code2:非递归;
- 首先把从root到p和q的路径都加入到parent中
- 然后在ancestor中存储p到根结点的路径
- 从q到根结点向上找,直到找到一个结点在ancestor中,该结点就是p、q的第一个最近公共祖先
/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */ class Solution { public: TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) { if(!root||!p||!q) return nullptr; unordered_map<TreeNode*,TreeNode*> parent; deque<TreeNode*> stack; parent[root]=nullptr; stack.push_back(root); while(!stack.empty()&&(find(stack.begin(),stack.end(),p)==stack.end()||find(stack.begin(),stack.end(),q)==stack.end())) { TreeNode* node=stack.back(); stack.pop_back(); if(node&&node->left) { stack.push_back(node->left); parent[node->left]=node; } if(node&&node->right) { stack.push_back(node->right); parent[node->right]=node; } } unordered_set<TreeNode*> ancerstor; while(p) { ancerstor.insert(p); p=parent[p]; } while(ancerstor.find(q)==ancerstor.end()) q=parent[q]; return q; } };