樹中兩結點的最低公共祖先(C 實現)

2021-07-31 01:51:19 字數 2879 閱讀 9697

題目是,輸入兩個樹結點,求它們的最低公共祖先

首先,要說明的是,這是一組題目,根據劍指offer上所講的,這道題可能會分好幾種情況,因此,如果在面試時候遇到,我們需要和面試官溝通,而不是一上來就寫**。

二叉搜尋樹(又叫二叉排序樹),中序遍歷是可以得到有序序列的,因此,我們可以利用這個性質來解題。

假設給定的兩個樹結點為4,1,根據圖示,顯然3為最低公共祖先;

假設給定的兩個樹結點為4,3,根據圖示,顯然3為最低公共祖先;

假設給定的兩個樹結點為2,1,根據圖示,顯然2為最低公共祖先;

假設給定的兩個樹結點為6,8,根據圖示,顯然7為最低公共祖先;

假設給定的兩個樹結點為8,1,根據圖示,顯然5為最低公共祖先;

因此我們發現,公共祖先的值都是在給定兩個樹結點的範圍之內。

所以,我們可以由根結點遍歷,如果當前結點的值比兩結點大,需要到當前結點的左子樹中找,如果當前結點的值比兩結點小,需要到當前結點的右子樹中找,僅當當前結點的值在兩結點的範圍內(等於也算)

**比較簡單,如下:

假設我們給定的結點為g,e,顯然由圖示,最低公共祖先為b。

由於有了指向父結點的指標,因此我們可以由g,e出發,找到最低公共祖先,所以此題其實本質是兩個鍊錶的第乙個公共結點。

鍊錶求交問題不難,有不少方法,比如可以先把g,e到根節點a所經過的所有結點壓棧,此時有兩個序列,

gdba,eba,兩棧棧頂相同pop,最後乙個相同的結點即為所求結果,這樣的演算法需要借助兩個棧(其他類似容器也可以)。

在這裡,我給出一種不需要借助容器的演算法,分別由g,e遍歷到根節點得到各自的長度,4和3,讓長度長一點的那個鍊錶先走一步,比如g先走到d,此時序列為dba和eba,同時走,遇到相同的結點即為所求結果。

**如下:

node* findlowestcommonancestor(node* root, node* n1, node* n2)

while (p2 !=

null)

if (count1 >= count2)

}else

}while (p1 != p2)

return p1;

}

我們往往可能遇到更一般的情況,也就是給定樹只是普通的二叉樹。那麼這道題如何解?

我們還是以之前的圖來看,不過需要注意的是此時沒有指向父節點的指標。

其實,我們可以模擬第一種情況(二叉搜尋樹)的解法,我們舉例來分析:

假設給定樹結點為d,e,求最低公共結點。我們由根節點a出發,d,e都在a的左子樹中,於是我們遍歷到b,此時d,e分別在b的左右子樹中,b即為所求答案。

假設給定樹結點為e,h,我們由a結點出發,發現e,h都在它的左子樹中,於是我們遍歷到b,發現他們都在b的右子樹中,於是我們遍歷到了e,此時e為所求答案。

因此,我們發現,如果給定的兩個樹結點都在當前結點的左子樹裡面,最低公共祖先必在左子樹中,如果給定的兩個樹結點都在當前結點的右子樹裡面,最低公共祖先必在右子樹中,如果不滿足這兩個條件,當前結點即為最低公共祖先。

思路有了,我們需要完成**

//判斷某個結點在當前樹中

bool isinthebinarytree(node* root, node* n)

node* findlowestcommonancestor(node* root, node* n1, node* n2)

我們已經完成基本功能了,然而我們仔細分析下**發現,我們判斷某個結點在樹中遞迴了一次樹,求公共結點又遞迴了一次樹,這樣子會對某些結點重複遍歷很多次,效率比較低,能否有乙個更好的演算法?

為了解決這個問題,我們需要儲存從根節點到兩個給定樹結點的路徑,這樣子由變成了求鍊錶的最後公共結點了。還是拿上面的圖舉例:

求g,e的最低公共祖先。

由a到g的路徑為:abdg

由a到e的路徑為:abe

如果看作是鍊錶,我們只需要求最後乙個公共交點了,當然借助其他類似容器也是同樣的道理,這裡我使用vector儲存路徑。

bool getpath(node* root, node* n, vector

& v)

v.push_back(root);

bool found = false;

found = getpath(root->left, n, v);

if (!found)

found = getpath(root->right, n, v);

if (!found)

v.pop_back();

return found;

}node* findlowestcommonancestor(node* root, node* n1, node* n2)

return v1[i - 1];

}else

}

樹中兩個結點的最低公共祖先

題目 輸入兩個樹結點,求它們的最低公共祖先 題目一 如果這個樹是二叉搜尋樹,二叉搜尋樹是排序過的,位於左子樹的結點都比父結點小,而位於右子樹的結點都比父結點大,我們只需要從樹的根結點開始和兩個輸入的結點比較,如果輸入兩個結點都比根結點小,那麼最低的共同父結點一定在當前結點的左子樹中,於是下一步遍歷當...

樹中兩個結點的最低公共祖先

在進行這個問題之前,我們需要考慮以下幾個問題 1 題目告訴我們是樹,但是沒有告訴我們是一棵怎樣的樹。這裡的樹可以分為三種結構。第一種 普通的二叉樹 第二種 結點中含有指向父親結點的指標 第三種 二叉搜尋樹。2 對於不同結構的樹,處理的方式是不一樣的,時間複雜度也是不一樣的,我們需要針對每種結構設計解...

樹中兩個結點的最低公共祖先

場景一 二叉搜尋樹bst 假設是二叉搜尋樹 二叉搜尋樹是乙個排序的二叉樹,左子樹的結點小於根結點,右子樹的結點大於根結點 故找到乙個結點,使其大於左子結點小於右子結點即可。public static treenode getlastcommonnode treenode proot,treenode...