1. 程式人生 > >程式設計師面試一百題-04-在二元樹中找出和為某值的所有路徑

程式設計師面試一百題-04-在二元樹中找出和為某值的所有路徑

1-題目 :
輸入一個整數和一棵二元樹;從樹的根結點開始往下訪問一直到葉結點所經過的所有結點形成一條路徑;打印出和與輸入整數相等的所有路徑。

2-示例 :
輸入整數22和如下二元樹,則應答應出兩條路徑10-12和10-5-7。
二元樹

3-思路 :
3.1-當訪問到某一結點時,把該結點新增到路徑上,並累加當前結點的值;
3.2-如果當前結點為葉結點並且當前路徑的和剛好等於輸入的整數,則當前的路徑符合要求,打印出來;如果當前結點不是葉結點,則繼續訪問它的子結點。
3.3-當前結點訪問結束後,遞迴函式將自動回到父結點,因此我們在函式退出之前要在路徑上刪除當前結點並減去當前結點的值,以確保返回父結點時路徑剛好是根結點到父結點的路徑。不難看出儲存路徑的資料結構實際上是一個棧結構,因為路徑要與遞迴呼叫狀態一致,而遞迴呼叫本質就是一個壓棧和出棧的過程。

4-程式碼 :

//二元樹節點的資料結構定義
struct BinaryTreeNode
{
    int m_nValue;
    BinaryTreeNode *m_pLeft;
    BinaryTreeNode *m_pRight;
};

//找出和為某值的路徑
//引數列表 : [二元樹的一個結點, 期待的某值, 當前路徑, 當前的和]
void FindPath(BinaryTreeNode *pTreeNode, int expectedSum, std::vector<int> &path, int &currentSum)
{
    //若該結點為空,則返回
    if (!pTreeNode)
    {
        return;
    }

    currentSum += pTreeNode->m_nValue;
    path.push_back(pTreeNode->m_nValue);

    //若該結點沒有左右子樹,則為葉子結點
    bool isLeaf = (!pTreeNode->m_pLeft && !pTreeNode->m_pRight);
    //如果該結點是葉子結點並且當前和為期待和,則輸出該路徑
    if (currentSum == expectedSum && isLeaf)
    {
        std::vector<int>::iterator iter = path.begin();
        while (iter != path.end())
        {
            std::cout << *iter << " ";
        }
        std::cout << std::endl;
    }

    //如果該結點不是葉子結點,則轉到它的孩子
    if (pTreeNode->m_pLeft)
    {
        FindPath(pTreeNode->m_pLeft, expectedSum, path, currentSum);
    }
    if (pTreeNode->m_pRight)
    {
        FindPath(pTreeNode->m_pRight, expectedSum, path, currentSum);
    }

    //當該結點訪問結束,返回到它的父結點並,然後路徑中刪除該結點,最後從當前和中減去該結點的值
    currentSum -= pTreeNode->m_nValue;
    path.pop_back();
}