尋找最近公共祖先節點(LCA)
在一棵二叉樹中,對於節點X和節點Y,X和Y的LCA是這棵樹中X和Y的第一個共同祖先。尋找公共節點的算法思路很簡單:對於節點x和y,找到樹的根節點分別到x節點和y節點的路徑(並不是遍歷),並分別記錄在兩個數組中(或其他),數組中索引為0的元素為樹的根節點,索引越小的元素離待x和y節點越遠。且兩個數組前面肯定有對應相同的元素。此時問題變為正向查找兩個數組中第一個不相同元素的前一個(相同),即最后一個相同的元素。
1.如果這棵二叉樹是二叉查找樹,那么記錄根節點到x和y節點的路徑問題變得很簡單,借助於二叉查找樹的性質,借助BST的查找過程,很簡單便可以做到。例:leetcode_235 LowestCommon Ancestor of a Binary Search Tree:Given a binary search tree (BST), find the lowest common ancestor (LCA) of two given nodes in the BST.
代碼:
/**
* 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:
void find1(TreeNode* root,TreeNode* p,vector<TreeNode*> &v)
{
if(root == p)
{
v.push_back(root);
return ;
}
if(p->val > root->val)
{
v.push_back(root);
find1(root->right,p,v);
}
else
{
v.push_back(root);
find1(root->left,p,v);
}
}
public:
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
if(root == NULL || p == NULL || q == NULL)
return NULL;
vector<TreeNode*> v1;
vector<TreeNode*> v2;
find1(root,p,v1);
find1(root,q,v2);
int i,j;
//cout<<v1.size()<<endl;
//cout<<v2.size()<<endl;
for(i = 0,j = 0;i<v1.size()-1,j<v2.size()-1;i++,j++)
{
if(v1[i] == v2[j] && v1[i+1] != v2[j+1])
break;
}
return v1[i];
}
};
2.若一棵樹是普通的二叉樹,則二叉排序樹在查找方面的特性不能應用。在普通二叉樹中,尋找從根節點到任意節點的路徑不像是在BST中那么簡單,我們先要解決這個問題。例:leetcode-236 Lowest Common Ancestor of a Binary Tree
bool findP(TreeNode *root,TreeNode *p,vector<TreeNode*> &v)//遞歸查找,路徑記錄在v中
{
if(p==NULL || root == NULL)
return false;
v.push_back(root);
if(root == p)
return true;
if(root->left != NULL && findP(root->left,p,v) == true )
{
return true;
}
if(root->right != NULL && findP(root->right,p,v) == true)
{
return true;
}
v.pop_back();//在該子樹上查找失敗,則刪除這個根節點
return false;
}
接下來的思路和上述一樣,正向查找兩個數組中第一個不相同元素的前一個(相同),即最后一個相同的元素。
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q)
{
if(root == NULL || p == NULL || q == NULL)
{
return NULL;
}
vector<TreeNode *> v1;
findP(root,p,v1);
vector<TreeNode*> v2;
findP(root,q,v2);
int len = v1.size()<v2.size()?v1.size():v2.size();
int i = 0;
for(i = 0;i<len-1;i++)
{
if(v1[i] == v2[i] && v1[i+1]!=v2[i+1])
break;
}
return v1[i];
}
