1. 程式人生 > >LeetCode 二叉樹的路徑遍歷

LeetCode 二叉樹的路徑遍歷

LeetCode 112. 路徑總和

題目描述: 給定一個二叉樹和一個目標和,判斷該樹中是否存在根節點到葉子節點的路徑,這條路徑上所有節點值相加等於目標和。

示例: 
給定如下二叉樹,以及目標和 sum = 22,

              5
             / \
            4   8
           /   / \
          11  13  4
         /  \      \
        7    2      1
返回 true, 因為存在目標和為 22 的根節點到葉子節點的路徑 5->4->11->2。

題目分析: 從根結點遍歷到葉結點,本質上就是二叉樹的深度遍歷,利用遞迴即可實現。程式碼如下:

bool hasPathSum(TreeNode* root, int sum) {
        if(root == NULL)
            return false;
        else if(root->left == NULL && root->right == NULL && root->val == sum)   //在葉結點時判斷結點的值與當前的sum值是否相等
            return true;
        else
            return hasPathSum(root->
left, sum-root->val) || hasPathSum(root->right, sum-root->val); }

LeetCode 113. 路徑總和 II

題目描述: 給定一個二叉樹和一個目標和,找到所有從根節點到葉子節點路徑總和等於給定目標和的路徑。

示例:
給定如下二叉樹,以及目標和 sum = 22,

              5
             / \
            4   8
           /   / \
          11  13  4
         /  \    / \
        7    2  5   1
返回:

[
   [5,4,11,2],
   [5,8,4,5]
]

題目分析: 與上一題類似,同樣需要遞迴進行深度遍歷來依次訪問從根結點到任意一個葉結點的一條路徑,此外,還需要一個路徑陣列來儲存一條完整路徑(根結點到某一個葉結點)的每個元素的值,若該路徑符合要求,則把該陣列儲存在一個儲存所有符合要求的路徑的陣列中。需要注意的是,路徑陣列要隨時保持更新,程式碼如下:

public:
    vector<vector<int>> pathSum(TreeNode* root, int sum) {
        help(root, sum);
        return v1;
    }
    void help(TreeNode* root, int sum){
        if(root == NULL)
            return;
        v2.push_back(root->val);   //每次訪問一個新結點時,將結點新增至路徑陣列中
        if(root->left == NULL && root->right == NULL){
            if(root->val == sum)   //判斷整個路徑是否滿足要求
                v1.push_back(v2);
        }
        else{
            help(root->left,sum-root->val);
            help(root->right, sum-root->val);
        }
        v2.pop_back();            //每次結束一個結點的訪問時,都要將該結點從路徑陣列中移除,以此做到路徑中的結點不會重複
    }
private:
    vector<vector<int>> v1;  //用來儲存所有滿足要求的路徑的陣列
    vector<int> v2;          //儲存路徑的陣列

總結:二叉樹從根結點開始到葉結點結束的路徑遍歷,本質上都是深度遍歷,都是通過遞迴的方法來實現的,對於不同的題目,在遞迴的過程中都有不同的操作,例如II中的不斷更新路徑陣列中的結點,對於初學者來說可能不好理解,建議多手動的跑程式碼,用紙筆親自操作,會加深自己的理解。