题目:
解答:
(递归) O(n)
当我们用递归去做这个题时不要被题目误导,应该要明确一点:这个函数的功能有三个:给定两个节点 p和 q
(1)如果 p 和 q 都存在,则返回它们的公共祖先;
(2)如果只存在一个,则返回存在的一个;
(3)如果 p 和 q 都不存在,则返回NULL
本题说给定的两个节点都存在,那自然还是能用上面的函数来解决
具体思路:
(1) 如果当前结点 root等于NULL,则直接返回NULL;
(2) 如果 root 等于 p或者 q ,那这棵树一定返回 p或者 q;
(3) 然后递归左右子树,因为是递归,使用函数后可认为左右子树已经算出结果,用 left 和 right 表示;
(4) 此时若left为空,那最终结果只要看 right;若 right为空,那最终结果只要看 left;
(5) 如果 left 和 right 都非空,因为只给了 p 和 q 两个结点,都非空,说明一边一个,因此 root 是他们的最近公共祖先;
(6) 如果 left 和 right都为空,则返回空(其实已经包含在前面的情况中了);
时间复杂度是O(n):每个结点最多遍历一次或用主定理,空间复杂度是O(n):需要系统栈空间。
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 public: 12 TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) 13 { 14 if(root == NULL) 15 { 16 return NULL; 17 } 18 if(root == p || root == q) 19 { 20 return root; 21 } 22 23 TreeNode* left = lowestCommonAncestor(root->left, p, q); 24 TreeNode* right = lowestCommonAncestor(root->right, p, q); 25 26 if(left == NULL) 27 return right; 28 if(right == NULL) 29 return left; 30 if(left && right) // p和q在两侧 31 return root; 32 33 return NULL; // 必须有返回值 34 } 35 };