劍指offer面試題25-二叉樹中和韋某一值的路徑
question:給定一顆二叉樹,一個值。我們希望輸出和為該值的所有路徑。
假設樹的結構如下
思路:使用一個基於先序遍歷的遞迴過程來遍歷樹中每個點一次,每遍歷一個點就要獲得從根節點到被訪問的點的累加和,並儲存從根節點到當前點的路徑。然後進行判斷,
case1如果當前點的左右孩子都為空(葉子節點)並且累加和等於我們期望的和,那麼就打印出路徑;
case2如果左孩子為空,遞迴到最孩子;
case3如果右孩子為空,遞迴到右孩子;
case4如果是葉子並且當前和不等於期望和,網上回退
試下程式碼:
引數為值傳遞的程式碼
注意:在這個程式碼中存放累加和curSum、路徑path的變數都是使用的值傳遞,而不是引用傳遞。因為該方法是一個遞迴的過程,在每一個遞迴棧中都有一個臨時變數curSum和path。如果遞迴返回到上一層時,本次計算的沒有影響。相反,如果使用了引用傳遞的,需要手動修改資料的值:#include<vector> #include<iostream> using namespace std; typedef struct BinaryTreeNode { int data; struct BinaryTreeNode *lchild; struct BinaryTreeNode *rchild; }*BinTreeRoot; void createTree1(BinaryTreeNode *&root) { root = (BinaryTreeNode *)malloc(sizeof(BinaryTreeNode)); root->data = 8; root->lchild = NULL; root->rchild = NULL; BinaryTreeNode *p = (BinaryTreeNode *)malloc(sizeof(BinaryTreeNode)); p->data = 8; p->lchild = NULL; p->rchild = NULL; root->lchild = p; p = (BinaryTreeNode *)malloc(sizeof(BinaryTreeNode)); p->data = 7; p->lchild = NULL; p->rchild = NULL; root->rchild = p; p = (BinaryTreeNode *)malloc(sizeof(BinaryTreeNode)); p->data = 9; p->lchild = NULL; p->rchild = NULL; root->lchild->lchild = p; p = (BinaryTreeNode *)malloc(sizeof(BinaryTreeNode)); p->data = 2; p->lchild = NULL; p->rchild = NULL; root->lchild->rchild = p; p = (BinaryTreeNode *)malloc(sizeof(BinaryTreeNode)); p->data = 4; p->lchild = NULL; p->rchild = NULL; root->lchild->rchild->lchild = p; p = (BinaryTreeNode *)malloc(sizeof(BinaryTreeNode)); p->data = 7; p->lchild = NULL; p->rchild = NULL; root->lchild->rchild->rchild = p; } void findPath(BinaryTreeNode *root, int expectedSum, int curSum, vector<int>path) { if (root == NULL) return; curSum += root->data; path.push_back(root->data); if (root->lchild == NULL && root->rchild == NULL && curSum == expectedSum) { for (auto iter = path.begin(); iter != path.end(); ++iter) { if (iter + 1 == path.end()) { cout << *iter << endl; } else { cout << *iter << "->"; } } } if (root->lchild != NULL) { findPath(root->lchild, expectedSum, curSum, path); } if (root->rchild != NULL) { findPath(root->rchild, expectedSum, curSum, path); } // curSum -= root->data; // path.pop_back(); } int main() { BinaryTreeNode *root = NULL; createTree1(root); if (root == NULL) { cout << "the tree is empty!" << endl; return 0; } int curSum = 0;//存放從根節點到當前節點的路徑和 int expectedSum;//我們期待的值 cin >> expectedSum; vector<int>path;//存放路徑 findPath(root, expectedSum, curSum, path); return 0; }
引數為引用傳遞的程式碼:
#include<vector> #include<iostream> using namespace std; typedef struct BinaryTreeNode { int data; struct BinaryTreeNode *lchild; struct BinaryTreeNode *rchild; }*BinTreeRoot; void createTree1(BinaryTreeNode *&root) { root = (BinaryTreeNode *)malloc(sizeof(BinaryTreeNode)); root->data = 8; root->lchild = NULL; root->rchild = NULL; BinaryTreeNode *p = (BinaryTreeNode *)malloc(sizeof(BinaryTreeNode)); p->data = 8; p->lchild = NULL; p->rchild = NULL; root->lchild = p; p = (BinaryTreeNode *)malloc(sizeof(BinaryTreeNode)); p->data = 7; p->lchild = NULL; p->rchild = NULL; root->rchild = p; p = (BinaryTreeNode *)malloc(sizeof(BinaryTreeNode)); p->data = 9; p->lchild = NULL; p->rchild = NULL; root->lchild->lchild = p; p = (BinaryTreeNode *)malloc(sizeof(BinaryTreeNode)); p->data = 2; p->lchild = NULL; p->rchild = NULL; root->lchild->rchild = p; p = (BinaryTreeNode *)malloc(sizeof(BinaryTreeNode)); p->data = 4; p->lchild = NULL; p->rchild = NULL; root->lchild->rchild->lchild = p; p = (BinaryTreeNode *)malloc(sizeof(BinaryTreeNode)); p->data = 7; p->lchild = NULL; p->rchild = NULL; root->lchild->rchild->rchild = p; } void findPath(BinaryTreeNode *root, int expectedSum, int &curSum, vector<int>&path)//引用傳遞 { if (root == NULL) return; curSum += root->data; path.push_back(root->data); if (root->lchild == NULL && root->rchild == NULL && curSum == expectedSum) { for (auto iter = path.begin(); iter != path.end(); ++iter) { if (iter + 1 == path.end()) { cout << *iter << endl; } else { cout << *iter << "->"; } } } if (root->lchild != NULL) { findPath(root->lchild, expectedSum, curSum, path); } if (root->rchild != NULL) { findPath(root->rchild, expectedSum, curSum, path); } curSum -= root->data;//curSum和path是引用傳遞,所以如果遞迴返回到上一層的時候,需要減去本次的累加 path.pop_back(); } int main() { BinaryTreeNode *root = NULL; createTree1(root); if (root == NULL) { cout << "the tree is empty!" << endl; return 0; } int curSum = 0;//存放從根節點到當前節點的路徑和 int expectedSum;//我們期待的值 cin >> expectedSum; vector<int>path;//存放路徑 findPath(root, expectedSum, curSum, path); return 0; }
過程:假設我們希望輸出和為25的所有路徑;
設定以下變數:int curSum = 0;//存放當前累加和
int expectedSum = 25;//期待和
vector<int>path;//用於存放路徑
BinaryTreeNode *root;//指向樹中根節點的指標
(1)首先從根節點出發,curSum = 8,並且不是葉子節點,並且值不為35。
(2)由於是基於先序遍歷的,接下來我們訪問左孩子,累加和為8+8=16,仍然不是葉子節點。
(3)再訪問8的右孩子9,累加和為25,並且是葉子節點。此時打印出路徑
路徑為8->8->9
(4)使用一個遞迴的過程,然後向上回退到節點8,並且訪問8的右孩子2
(5)訪問2的左孩子4,此時累加和為22.
(6)當前訪問到的點4是一個葉子節點,並且累加和為22,不是我們所期待的,所以向上回退到2,並且訪問2的右孩子7,此時7是葉子節點。並且和為25,所以滿足要求,打印出路徑
路徑為:8->8->2->7