1.問題描述
寫一個程序求一棵二叉樹相距最遠的兩個節點之間的距離
如下圖:
2.分析與解法
對於任意一個節點,以該節點爲根,假設這個根有k個孩子節點,那麼距離最遠的兩個節點U與V之間的路徑與這個根節點的關係有兩種。
1)若路徑經過Root,則U和V是屬於不同子樹的,且它們都是該子樹中到根節點最遠的節點,否則跟它們的距離最遠相矛盾
2)如果路徑不經過Root,那麼它們一定屬於根的k個子樹之一,並且它們也是該子樹中相距最遠的兩個頂點
因此,問題就可以轉化爲在子樹上的解,從而能夠利用動態規劃來解決。
設第K棵子樹中相距最遠的兩個節點:Uk和Vk,其距離定義爲d(Uk,Vk),那麼節點Uk或Vk即爲子樹K到根節點Rk距離最長的節點。不失一般性,我們設Uk爲子樹K中到根節點Rk距離最長的節點,其到根節點的距離定義爲d(Uk,R)。取d(Ui,R)(1<=i<=k)中最大的兩個值max1和max2,那麼經過根節點R的最長路徑爲max1+max2+2,所以樹R中相距最遠的兩個點的距離爲:max{d(U1,V1),…, d(Uk,Vk),max1+max2+2}。
3.代碼實現
//數據結構定義
struct NODE
{
NODE* pLeft; //左孩子
NODE* pRight; //右孩子
int nMaxLeft; //左孩子中的最長距離
int nMaxRight; //右孩子中的最長距離
char chValue; //該節點的值
};
int nMaxLen=0;
//尋找樹中最長的兩段距離
void FindMaxLen(NODE* pRoot)
{
//遍歷到葉子節點,返回
if(pRoot==NULL)
{
return;
}
//如果左子樹爲空,那麼該節點的左邊最長距離爲0
if(pRoot->pLeft==NULL)
{
pRoot->nMaxLeft=0;
}
//如果右子樹爲空,那麼該節點的右邊最長距離爲0
if(pRoot->pRight==NULL)
{
pRoot->nMaxRight=0;
}
//如果左子樹不爲空,遞歸尋找左子樹最長距離
if(pRoot->pLeft!=NULL)
{
FindMaxLen(pRoot->pLeft);
}
//如果右子樹不爲空,遞歸尋找右子樹最長距離
if(pRoot->pRight!=NULL)
{
FindMaxLen(pRoot->pRight);
}
if(pRoot->pLeft!=NULL)
{
int nTempMax=0;
if(pRoot->pLeft->nMaxLeft > pRoot->pLeft->nMaxRight)
{
nTempMax=pRoot->pLeft->nMaxLeft;
}
else
{
nTempMax=pRoot->pLeft->nMaxRight;
}
pRoot->nMaxLeft=nTempMax+1;
}
//計算右子樹最長節點距離
if(pRoot->pRight!=NULL)
{
int nTempMax=0;
if(pRoot->pRight->nMaxLeft > pRoot->pRight->nMaxRight)
{
nTempMax= pRoot->pRight->nMaxLeft;
}
else
{
nTempMax= pRoot->pRight-> nMaxRight;
}
pRoot->nMaxRight=nTempMax+1;
}
//更新最長距離
if(pRoot->nMaxLeft+pRoot->nMaxRight > nMaxLen)
{
nMaxLen=pRoot->nMaxLeft+pRoot->nMaxRight;
}
}