LeetCode 437 Path Sum III

265 阅读2分钟

LeetCode 437 Path Sum III

思路

  1. 注意到这题与Path Sum II的不同。第一,path的起点可以不是root,第二,path的终点可以不是leaf。因此,每遍历到一个节点,该节点的左子节点或右子节点可能成为path的起点,pathSum函数专门处理起点的遍历。DFS函数专门处理路径和。

  2. 在递归的过程中,每次进入递归,将当前节点的val添加至path末尾,然后从path尾部开始往前遍历,若遇到满足条件的路径,则将cnt加一。然后再对左子树和右子树递归,退出递归时,将当前节点的val弹出。

代码

方法1

class Solution {
public:
    int pathSum(TreeNode* root, int sum) {
        if (!root) return 0;
        int cnt = 0;
        if (root->val == sum) ++cnt;
        cnt += pathSum(root->left, sum);
        cnt += pathSum(root->right, sum);
        cnt += DFS(root->left, sum - root->val);
        cnt += DFS(root->right, sum - root->val);
        
        return cnt;
    }
    
    int DFS(TreeNode *root, int sum) {
        if (!root) return 0;
        
        int cnt = 0;
        if (root->val == sum) ++cnt;
        cnt += DFS(root->left, sum - root->val);
        cnt += DFS(root->right, sum - root->val);
        
        return cnt;
    }
};

方法2

class Solution {
public:
    int pathSum(TreeNode* root, int sum) {
        if (!root) return 0;
        
        vector<int> vec;
        int cnt = 0;
        
        count(root, sum, cnt, vec);
        
        return cnt;
    }
    
    void count(TreeNode *root, int sum, int &cnt, vector<int> &vec) {
        if (!root) return ;
        
        vec.push_back(root->val);
        int s = 0;
        
        for (int i = vec.size() - 1; i >= 0; --i) {
            s += vec[i];
            if (s == sum) ++cnt;
        }
        
        count(root->left, sum, cnt, vec);
        count(root->right, sum, cnt, vec);
        vec.pop_back();
    }
};

方法1 优化代码

class Solution {
public:
    int pathSum(TreeNode* root, int sum) {
        if (!root) return 0;
        
        int cnt = 0;
        dfs(root, sum, cnt);
        
        cnt += pathSum(root->left, sum);
        cnt += pathSum(root->right, sum);
        
        return cnt;
    }
    
    void dfs(TreeNode *root, int sum, int &cnt) {
        if (!root) return ;
        
        if (root->val == sum) ++cnt;
        dfs(root->left, sum - root->val, cnt);
        dfs(root->right, sum - root->val, cnt);
    }
};

总结

对于起点不从root开始的题目,可以一个函数负责遍历起点,一个函数负责遍历以该点为起点的path。也可以从终点的角度开始考虑。方法2中,每次递归,path都有不同的终点,然后从终点往前遍历path,便可找到起点不在root的满足条件的path。