一刷劍指offer(25)——二叉樹中和爲某一值的路徑

題目:
輸入一顆二叉樹和一個整數,打印出二叉樹中結點值的和爲輸入整數的所有路徑。從樹的根結點開始往下,一直到葉結點所經過的結點形成一條路徑。二叉樹結點定義爲:
struct BinaryTreeNode
{
    int     m_nValue;
    BinaryTreeNode*    m_pLeft;
    BinaryTreeNode*    m_pRight;
};

由於路徑是從根結點出發到葉結點,因此路徑總是以根結點爲起始點,需要按照前序遍歷的順序遍歷二叉樹。

舉個例子來說明問題,假如輸入二叉樹如下,輸入的整數爲22:

前序遍歷,第一次從根結點到葉子結點:10-5-4,遍歷的同時將這3個結點加入路徑當中,值之和爲19,因此需要遍歷其他結點。在遍歷下一個結點之前,先要從結點4回到結點5,再去遍歷5的右子結點7。注意,回到5的時候,就應該將4移出路徑,後面遍歷7到時候,應該把7加入路徑,此時路徑爲10-5-7,值之和爲22,滿足。最後需要遍歷12,因此需要回到12的父結點10,同時刪除10的左子結點5,以及5的子結點7,此時路徑爲10-12,值之和爲22,滿足。

總結來說,當用前序遍歷的方式訪問某一結點時,我們把該結點添加到路徑上,並累加該結點的值。如果該結點爲葉結點並且路徑中結點值的和剛好等於輸入的整數,則當前路徑符合要求。如果當前結點不是葉結點,則繼續訪問它的子結點。當前結點訪問結束後,遞歸函數將自動回到它的父結點。因此我們在函數退出只前要在路徑上刪除當前結點並減去當前結點的值,以確保返回父結點時路徑剛好是從根結點到父結點的路徑。因爲路徑要與遞歸調用狀態一致,因此保存路徑的數據結構實際上是一個棧。

void FindPath(BinaryTreeNode* pRoot,int expectedSum,std::vector<int>& path,int& currentSum)
{
    currentSum+=pRoot->m_nValue;
    path.push_back(pRoot->m_nValue);
    //如果是葉結點,並且路徑上結點的和等於輸入的值,打印出路徑
    bool isLeaf=(pRoot->m_pLeft==NULL && pRoot->m_pRight==NULL);
    if(currentSum==expected && isLeaf)
    {
        cout<<"FOUND PATH:";
        std::vector<int>::iterator iter=path.begin();
        for(;iter!=path.end();++iter)
            cout<<iter<<"    ";
        cout<<endl;
    }
    //如果不是葉結點,則遍歷它的子結點
    if(pRoot->m_pLeft!=NULL)
        FindPath(pRoot->m_pLeft,expectedSum,path,currentSum);
    if(pRoot->m_Right!=NULL)
        FindPath(pRoot->m_pRight,expectedSum,path,currentSum);
    //返回父結點之前,刪除當前結點,並在currentSum中減去當前結點的值
    currentSum-=pRoot->m_nValue;
    path.pop_back();
}

void Find(BinaryTreeNode* pRoot,int expectedSum)
{
    if(pRoot==NULL)
        return;
    std::vector<int> path;
    int currentSum=0;
    FindPath(pRoot,expectedSum,path,currentSum);

}

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章