面试题 04.08. 首个共同祖先
设计并实现一个算法,找出二叉树中某两个节点的第一个共同祖先。不得将其他的节点存储在另外的数据结构中。注意:这不一定是二叉搜索树。
例如,给定如下二叉树: root = [3,5,1,6,2,0,8,null,null,7,4]
1 2 3 4 5 6 7
| 3 / \ 5 1 / \ / \ 6 2 0 8 / \ 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 为不同节点且均存在于给定的二叉树中。
解答
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
|
class Solution { public: TreeNode* tNode = NULL;
int checkRoot(TreeNode* root, TreeNode* p, TreeNode* q) { if (tNode || !root) { return 0; } int base = 0; if (root == p) { base = 1; } if (root == q) { base = 2; } int ans = base + checkRoot(root->left, p, q) + checkRoot(root->right, p, q); if (ans == 3 && !tNode) { tNode = root; } return ans; }
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) { tNode = NULL; checkRoot(root, p, q); return tNode; } };
|
其实没有必要去判断这个节点下面有左还是右还是都有,有一个更简单的做法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
|
class Solution { public: TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) { if (!root) { return NULL; } if (root == p || root == q) { return root; } TreeNode* left = lowestCommonAncestor(root->left, p, q); TreeNode* right = lowestCommonAncestor(root->right, p, q); if (left && right) { return root; } if (left) { return left; } if (right) { return right; } return NULL; } };
|
直接来判断可能是首个共同祖先。这个节点本身是p或者q的话,他就可能是首个共同祖先;如果左右子树里面不同时有p或者q的话,就肯定不是第一个共同祖先了。
另一种写法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
|
class Solution { public: TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) { if(root == nullptr || root == p || root == q) return root; TreeNode *left = lowestCommonAncestor(root->left,p,q); TreeNode *right = lowestCommonAncestor(root->right,p,q); if(left && right) return root; if(left) return left; return right; } };
|
如果要返回NULL的时候返回root自己,也不会有影响。