二叉樹中兩個節點的最低公共祖先
1、如果此二叉樹為二叉搜尋樹,即樹中所有結點的左子樹的結點都比父結點小,所有結點的右子樹都比父結點大
對於此種情況,我們只需從樹的根結點開始和輸入的兩個結點進行比較。如果當前結點的值比兩個結點的值都大,那麼最低的共同父結點一定是在當前結點的左子樹中,於是下一步遍歷當前結點的左子結點;如果當前結點的值比兩個結點的值都小,那麼最低的共同父結點一定是在當前結點的右子樹中,於是下一步遍歷當前結點的右子結點。這樣在樹中從上到下找到第一個在輸入結點的值之間的結點,就是最低的公共祖先。
struct BSNode
{
int _data;
BSNode* _left;
BSNode* _right;
BSNode(int data = 0) :_data(data), _left(NULL), _right(NULL)
{}
};
BSNode* GetLastCommonParent_1(BSNode* pRoot, BSNode* pNode1, BSNode* pNode2)
{
if (pRoot == NULL || pNode1 == NULL || pNode2 == NULL)
{
return NULL;
}
if (pNode1 == pNode2)
{
return pNode1;
}
BSNode* cur = pRoot;
while (true)
{
if ((cur->_data >= pNode1->_data&&cur->_data<=pNode2->_data) ||
(cur->_data>=pNode2->_data&&cur->_data <= pNode1->_data))
return cur;
else if (cur->_data>pNode1->_data)
{
cur = cur->_left;
}
else
{
cur = cur->_right;
}
}
return NULL;
}
2、如果此樹是含有父結點的二叉樹
對於此種情況,可以轉化為求兩個連結串列的第一個公共結點。假設樹結點中指向父結點的指標是_parent,那麼從樹每一結點開始都有一個由_parent串起來的連結串列,這些連結串列的尾指標都是根結點。輸入兩個結點,那麼這兩個結點位於兩個連結串列上,它們的最低公共祖先剛好就是這兩個連結串列的第一個公共結點。
struct BinTreePar
{
int _data;
BinTreePar* _left;
BinTreePar* _right;
BinTreePar* _parent;
BinTreePar(int data = 0) :_data(data), _left(NULL), _right(NULL), _parent(NULL)
{}
};
//求到根結點的路徑長度
int BinLen(BinTreePar* pRoot, BinTreePar* pNode)
{
int count = 0;
BinTreePar* cur = pNode;
while (cur != pRoot)
{
++count;
cur = cur->_parent;
}
return count;
}
BinTreePar* GetLastCommonParent_2(BinTreePar* pRoot, BinTreePar* pNode1, BinTreePar* pNode2)
{
if (pRoot == NULL || pNode1 == NULL || pNode2 == NULL)
{
return NULL;
}
if (pNode1 == pNode2)
{
return pNode1;
}
//類似相交單連結串列找相遇點
BinTreePar* curA = pNode1;
BinTreePar* curB = pNode2;
//計算到根節點的距離
int lenA = BinLen(pRoot, pNode1);
int lenB = BinLen(pRoot, pNode2);
int subLen = lenA - lenB;
if (subLen > 0)
{
while (subLen--)
{
curA = curA->_parent;
}
}
else if (subLen < 0)
{
while (subLen++)
{
curB = curB->_parent;
}
}
while (curA != curB)
{
curA = curA->_parent;
curB = curB->_parent;
}
return curA;
}
3、此樹是普通的二叉樹對於此種情況,我們需找到從根節點到輸入的兩個的路徑,然後有輔助的記憶體來儲存路徑,然後再從這兩條路徑中找出最後一個相同的結點。
#include <list>
struct BinTree
{
int _data;
BinTree* _left;
BinTree* _right;
BinTree(int data = 0) :_data(data), _left(NULL), _right(NULL)
{}
};
//尋找路徑
bool FindRoot(BinTree* pRoot, BinTree* pNode, list<BinTree*>& listRoot)
{
if (pRoot == NULL || pNode == NULL)
{
return true;
}
listRoot.push_back(pRoot);
if (pRoot == pNode)
{
return true;
}
if (pRoot->_left)
{
bool ret = FindRoot(pRoot->_left, pNode, listRoot);
if (ret)
{
return true;
}
}
if (pRoot->_right)
{
bool ret = FindRoot(pRoot->_right, pNode, listRoot);
if (ret)
{
return true;
}
}
listRoot.pop_back();
}
BinTree* GetLastCommonParent_3(BinTree* pRoot, BinTree* pNode1, BinTree* pNode2)
{
//找到由根節點到pNode1、pNode2的路徑,再找最後一個相同的結點,用list儲存路徑
if (pRoot == NULL || pNode1 == NULL || pNode2 == NULL)
{
return NULL;
}
if (pNode1 == pNode2)
{
return pNode1;
}
list<BinTree*> listRoot1;
list<BinTree*> listRoot2;
FindRoot(pRoot, pNode1, listRoot1);
FindRoot(pRoot, pNode2, listRoot2);
list<BinTree*>::iterator iteA = listRoot1.begin();
list<BinTree*>::iterator iteB = listRoot2.begin();
BinTree* ret = listRoot1.front();
list<BinTree*>::iterator end = listRoot1.end();
while (iteA != listRoot1.end() && iteB != listRoot2.end() && (*iteA)->_data == (*iteB)->_data)
{
ret = *iteA;
++iteA;
++iteB;
}
return ret;
}
相關文章
- 二叉樹兩個節點的公共節點二叉樹
- 二叉樹節點個數,葉子個數,第K層個數,最低公共節點二叉樹
- 二叉樹的最近公共祖先二叉樹
- 二叉搜尋樹和二叉樹的最近公共祖先二叉樹
- 樹上公共祖先(LCA)
- 二叉樹中相距最遠的兩個節點之間的距離二叉樹
- # 劍指 Offer 68 - II. 二叉樹的最近公共祖先二叉樹
- [1483. 樹節點的第 K 個祖先] 【路徑】
- Java二叉樹排序及任意兩點個節點間的最大距離Java二叉樹排序
- HDU 1330 Nearest Common Ancestors(求兩個點的最近公共祖先)REST
- 建立二叉樹:層次遍歷--樹的寬度高度,後序遍歷--祖先節點二叉樹
- 刷題系列 - 在給出二叉樹中兩個點,求出其最小共同父節點二叉樹
- leetcode 235. 二叉搜尋樹的最近公共祖先LeetCode
- Java中在二叉搜尋樹中查詢節點的父節點Java
- 程式碼隨想錄演算法訓練營第22天 |二叉樹part07:235. 二叉搜尋樹的最近公共祖先、701.二叉搜尋樹中的插入操作、450.刪除二叉搜尋樹中的節點演算法二叉樹
- 008,二叉樹的下一個節點二叉樹
- 快速求完全二叉樹的節點個數二叉樹
- 程式碼隨想錄演算法訓練營第19天|235. 二叉搜尋樹的最近公共祖先 ,701.二叉搜尋樹中的插入操作,450.刪除二叉搜尋樹中的節點演算法
- 程式碼隨想錄演算法訓練營day22 | leetcode 235. 二叉搜尋樹的最近公共祖先、701. 二叉搜尋樹中的插入操作、450. 刪除二叉搜尋樹中的節點演算法LeetCode
- 程式碼隨想錄演算法訓練營day19| 235. 二叉搜尋樹的最近公共祖先 701.二叉搜尋樹中的插入操作 450.刪除二叉搜尋樹中的節點演算法
- (117)235. 二叉搜尋樹的最近公共祖先(leetcode)LeetCode
- 二叉樹任意兩個節點間的最大距離(Java,LeetCode 543二叉樹的直徑 遞迴)二叉樹JavaLeetCode遞迴
- TCP 中的兩個細節點TCP
- 671. 二叉樹中第二小的節點二叉樹
- Day21 | 530.二叉搜尋樹的最小絕對差、501.二叉搜尋樹中的眾數 、236. 二叉樹的最近公共祖先二叉樹
- 二叉樹:距離最近的共同祖先二叉樹
- 為什麼二叉樹中葉子節點個數等於度為2的節點個數+1二叉樹
- Google S2 中的四叉樹求 LCA 最近公共祖先Go
- 二叉樹中最遠的兩個結點的距離二叉樹
- lc235.二叉搜尋樹的最近公共祖先【①分別得到祖先序列,然後比較;②***同時查詢,找出分岔結點】
- 程式碼隨想錄——二叉樹-11.完全二叉樹的節點個數二叉樹
- 最近公共祖先
- 刷題系列 - 在二叉樹中,為每個節點關聯其右相鄰節點二叉樹
- 程式碼隨想錄演算法訓練營第二十二天 | 235.二叉搜尋樹的最近公共祖先 701.二叉搜尋樹中的插入操作 450.刪除二叉搜尋樹中的節點演算法
- 22天【程式碼隨想錄演算法訓練營34期】第六章 二叉樹part08 (● 235. 二叉搜尋樹的最近公共祖先 ● 701.二叉搜尋樹中的插入操作 ● 450.刪除二叉搜尋樹中的節點)演算法二叉樹
- Git 中的演算法-最近公共祖先Git演算法
- 【leetcode 簡單】 第六十八題 二叉搜尋樹的最近公共祖先LeetCode
- 【vue】在二叉樹中根據子節點找出父節點路徑Vue二叉樹