微软面试题:LeetCode 236. 二叉树的最近公共祖先 出现次数:3
题目描述:给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。
写二叉树相关的算法,简单说就是,先搞清楚当前 root
节点该做什么,然后根据函数定义递归调用子节点,
递归调用会让左右孩子节点做相同的事情。
写递归算法的关键是要明确函数的「定义」是什么,然后相信这个定义,利用这个定义推导最终结果,
绝不要跳入递归的细节。
1 /** 2 * Definition for a binary tree node. 3 * struct TreeNode { 4 * int val; 5 * TreeNode *left; 6 * TreeNode *right; 7 * TreeNode(int x) : val(x), left(NULL), right(NULL) {} 8 * }; 9 */ 10 class Solution { 11 12 unordered_map<TreeNode*,int> count_map; 13 public: 14 TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) 15 { 16 //p、q 有一个是 根节点,根节点就是两者的 最近公共祖先 17 if(root == p || root == q) return root; 18 //分别计算 左右子树中 含有 p 、 q的数量 19 int left = serach_target(root->left,p,q); 20 int right = serach_target(root->right,p,q); 21 //p 、q 在左右子树 中一边一个,根节点就是两者的 最近公共祖先 22 if(left == 1 && right == 1) return root; 23 //p 、q 全在左子树中,递归地在 左子树中寻找 p q 公共祖先 24 else if(left == 2) 25 { 26 return lowestCommonAncestor(root->left,p,q); 27 } 28 //p 、q 全在右子树中,递归地在 右子树中寻找 p q 公共祖先 29 else if(right == 2) 30 { 31 return lowestCommonAncestor(root->right,p,q); 32 } 33 //上面已经把所有情况列举过,这里的仅仅return 仅为过编译 34 return NULL; 35 } 36 //统计root 中统计 含有的 p 、q数量 返回可能为 0,1,2 37 int serach_target(TreeNode* root, TreeNode* p, TreeNode* q) 38 { 39 if(root == NULL) return 0; 40 // if(count_map.find(root)!= count_map.end()) return count_map[root]; 41 int ret = 0; 42 if(root == p || root == q) ret++; 43 int left = serach_target(root->left,p,q); 44 int right = serach_target(root->right,p,q); 45 //count_map[root] = ret + left +right; 46 return ret + left +right; 47 } 48 };
别人更简洁的代码:
1 class Solution { 2 public: 3 TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) { 4 if(root==NULL) return NULL; 5 if(root==p||root==q) return root; //在同一支,父子孙节点 6 7 TreeNode*left=lowestCommonAncestor(root->left, p, q); 8 TreeNode*right=lowestCommonAncestor(root->right, p, q); 9 10 if(left==NULL) return right; 11 else if(right==NULL) return left; 12 else return root; //root在p,q中间 (left!=NULL&&right!=NULL) 13 } 14 }; 15 //left==NULL&&right==NULL 本题说给定的两个节点都存在,所以不需要考虑这种情况