微软面试题: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   本题说给定的两个节点都存在,所以不需要考虑这种情况

 

posted @ 2020-11-14 16:40  谁在写西加加  阅读(90)  评论(0编辑  收藏  举报