每日leetcode-面试题-04-08-

面试题 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
/**
* 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* 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
/**
* 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) {
// 返回最低的共同祖先,如果p和q中只有一个元素在下面的话就返回这个元素
if (!root) {
return NULL;
}
if (root == p || root == q) { // 如果root就是p或者q,就说明root是共同祖先或者是p和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
/**
* 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) {
// 返回最低的共同祖先,如果p和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自己,也不会有影响。