Given a binary tree, find the lowest common ancestor (LCA) of two given nodes in the tree.
According to the definition of LCA on Wikipedia: “The lowest common ancestor is defined between two nodes p and q as the lowest node in T that has both p and q as descendants (where we allow a node to be a descendant of itself).”
Given the following binary tree: root = [3,5,1,6,2,0,8,null,null,7,4]
Example 1:
Input: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
Output: 3
Explanation: The LCA of nodes 5 and 1 is 3.
Example 2:
Input: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4
Output: 5
Explanation: The LCA of nodes 5 and 4 is 5, since a node can be a descendant of itself according to the LCA definition.
Note:
All of the nodes’ values will be unique.
p and q are different and both values will exist in the binary tree.
题意: 就是找出两个节点(p,q)的最近公共祖先。
首先思路:
1: 如果存在某一个节点(root),p存在于root的左子树,而q存在于root的右子树,那么root必然是p,q节点的最近公共祖先。
2: 如果p,q节点存在于root的左子树或者右子树,那么可以继续递归下去。
代码:
class Solution
{
public:
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q)
{
// 如果都在左子树,那么继续递归下去
if(hasNode(root->left, p) && hasNode(root->left, q))
return lowestCommonAncestor(root->left, p, q);
if(hasNode(root->right, p) && hasNode(root->right, q))
return lowestCommonAncestor(root->right, p, q);
return root;
}
bool hasNode(TreeNode*root, TreeNode* p)
{
if(root == nullptr) return false;
if(root == p) return true;
return hasNode(root->left, p) || hasNode(root->right, p);
}
};
这种方法是二叉树的每个节点都要进行遍历,所以时间复杂度为O(n^2).但是也是最容器理解的。
方法2 :也是同样的原理,但是自底向上的。也是同样的原理,如果左右节点都存在,那么必然这个root是最小公共祖先。
代码:
class Solution
{
public:
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q)
{
if(root == nullptr) return nullptr;
if(root == p || root ==q) return root;
TreeNode* L = lowestCommonAncestor(root->left, p, q);
TreeNode* R = lowestCommonAncestor(root->right, p ,q);
if (L) cout << L->val << endl;
if(L && R) return root;
return L?L:R;
}
};
方法3:针对p,q直接找到其路径,然后找到最后一个相同的点即可,求的就是最近公共祖先。
class Solution
{
public:
void print(vector tmp)
{
for(int i = 0; i < tmp.size(); i++)
{
if(i == tmp.size()-1) cout << tmp[i]->val << endl;
else cout << tmp[i]->val << " ";
}
}
void findpath(TreeNode* root, TreeNode* p, vectortmp_path, vectorans, bool &ok)
{
if(root == nullptr) return;
if(ok) return;
tmp_path.push_back(root);
if(root == p)
{
ok = true;
for(int i = 0; i < tmp_path.size(); i++) ans.push_back(tmp_path[i]);
return;
}
findpath(root->left, p, tmp_path, ans, ok);
findpath(root->right, p, tmp_path, ans, ok);
tmp_path.pop_back();
}
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q)
{
vector path_p, path_q;
vector tmp_path;
TreeNode* parent;
bool ok = false;
findpath(root, p, tmp_path, path_p, ok);
// print(path_p);
ok = false;
tmp_path.clear();
findpath(root, q, tmp_path, path_q, ok);
// print(path_q);
for(int i = 0; i < path_p.size(); i++)
{
ok = false;
for(int j = 0; j < path_q.size(); j++)
{
if(path_p[i] == path_q[j])
{
ok = true;
break;
}
}
if(!ok)
{
parent = path_p[i-1];
break;
}
}
if(ok) return path_p[path_p.size()-1];
return parent;
}
};
int main()
{
TreeNode* p1 = new TreeNode(1);
TreeNode* p2 = new TreeNode(2);
TreeNode* p3 = new TreeNode(3);
TreeNode* p4 = new TreeNode(4);
TreeNode* p5 = new TreeNode(5);
TreeNode* p6 = new TreeNode(6);
TreeNode* p7 = new TreeNode(7);
TreeNode* p8 = new TreeNode(8);
p1->left = p2;
p1->right = p3;
p2->left = p4;
p2->right = p5;
p3->left = p6;
p3->right = p7;
p4->left = p8;
Solution so;
cout << so.lowestCommonAncestor(p1, p4, p8)->val << endl;
return 0;
}