1. 程式人生 > >leetcode刷題(六)路徑總和I、II、III

leetcode刷題(六)路徑總和I、II、III

(一)112題

題目地址:https://leetcode-cn.com/problems/path-sum/description/

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

解決方案:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    bool hasPathSum(TreeNode* root, int sum) {
        if(root==NULL){
            return false;
         }
        int t=sum-root->val;
        if(root->left==NULL&& root->right==NULL){
             return t==0 ? true :false;
        }  
        //遞迴呼叫函式,分別判斷根結點的左節點和右節點
        return hasPathSum(root->left,t) || hasPathSum(root->right,t);
    }

};


備註:這裡的解決方案,採用遞迴呼叫的形式,每次開始都從sum中減去到根結點的值,然後再判斷當前的節點作為根結點到其左孩子和右孩子的距離與t的關係。

效能分析:

大神的寫法就是厲害,這個故事告訴我們遞迴呼叫效能真的很優,下次直覺想到迴圈呼叫的時候,可以考慮一下遞迴呼叫

(二)113題

題目地址:https://leetcode-cn.com/problems/path-sum-ii/description/

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

解決方案:

class Solution {
public:
    vector<vector<int>> pathSum(TreeNode* root, int sum) {
        vector<vector<int>> res;
        vector<int> out;
        worker(root,sum,out,res);
        return res;  
    }
    //遞迴呼叫,實現對節點的路徑總和判斷和路徑記錄功能
    void worker(TreeNode* node,int sum,vector<int>& out,vector<vector<int>>& res){
        if(!node) return;
        out.push_back(node->val);
        if(sum==node->val && !node->left && !node->right)
        {
            res.push_back(out);
        }
        worker(node->left,sum-node->val,out,res);
        worker(node->right,sum-node->val,out,res);
        out.pop_back();
    }
        
};


備註:同樣使用遞迴呼叫,但由於程式碼較長,多寫了一個函式,函式實現對二叉樹中不同節點的處理進行記錄。其中res為滿足要求或者等待判斷的當前路徑,out是在新加入的路徑不符合要求時,退出的節點。

效能分析:

說明:這個故事告訴我們遇到不會的問題,參考學習大神的程式碼沒有問題,哪怕學習思路漲漲見識也好

(三)437題

給定一個二叉樹,它的每個結點都存放著一個整數值。

找出路徑和等於給定數值的路徑總數。

路徑不需要從根節點開始,也不需要在葉子節點結束,但是路徑方向必須是向下的(只能從父節點到子節點)。

二叉樹不超過1000個節點,且節點數值範圍是 [-1000000,1000000] 的整數。

解決方案:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    int pathSum(TreeNode* root, int sum) {
        int cnt = 0;
        dfs1(root, sum, cnt);
        return cnt;
        }
    //dfs用來計算二叉樹中符合要求的路徑的長度
    void dfs(TreeNode* root, int sum, int& cnt){
         if(root == NULL) return;
        //累計符合要求的路徑個數
       if(root->val == sum) cnt++;
        dfs(root->left, sum-root->val, cnt);
        dfs(root->right, sum-root->val, cnt);
     }
    //用來遍歷每個節點
    void dfs1(TreeNode* root, int sum, int& cnt){
         if(root == NULL) return;
        dfs(root, sum, cnt);
        dfs1(root->left, sum, cnt);
        dfs1(root->right, sum, cnt);
    }

};

分析:較II題多了一個遍歷二叉樹節點的函式

效能分析:


分析:看了三篇大神寫的程式碼,發現實現相同功能的不同寫法,其實可以相互借鑑一下