437. Path Sum III

今天继续刷leetcode呀!

这道题是leetcode 第437题 Path Sum III ,这道题意思是找出一棵二叉树中所有从上往下的路径,这些路径中的结点的权值之和等于题目给定的target。这里有一个要求,就是路径的起点不需要是整棵二叉树的根结点,路径的终点也不需要是叶子结点。只要是从上往下的路径就行,当然也不能包含重复结点。

这个问题既然是二叉树的,那么一般是用递归的方式来做。

直接分析该问题会发现,路径的终点不确定好说,因为递归就是从整棵树的起点出发,依次往下进行的,我们可以在递归到某个结点的时候判断当前路径符不符合要求,符合要求的话就添加到结果中。

但是递归起点不确定可不好做,所以,我们先把这道题转变一下,其他条件不变,仅要求路径的起点是整棵树的根结点,于是我们可以写出如下代码:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    int pathSum(TreeNode* root, int sum) {
        if (!root) return 0;
        vector<int> path;
        int cnt = 0;
        helper(root, sum, 0, path, cnt);
        return cnt;
    }

    void helper(TreeNode* root, int sum, int out, vector<int>& path, int& cnt) {
        if (root) {
            path.push_back(root->val);
            out += root->val;
            if (out == sum) cnt++;

            helper(root->left, sum, out, path, cnt);
            helper(root->right, sum, out, path, cnt);

            path.pop_back();
        }
    }
};

这个应该没啥问题,很多人做到这里不会做了,因为一看起点不固定怎么办?如果你去想着改造一下helper函数来达到原问题的要求那大概是有点难。

这里我们有个技巧,就是改造一下原始函数,你想一下,对于某个结点,我们可以从它开始寻找符合要求的路径,也可以从它下面的孩子结点开始寻找,于是,我们简单修改一下pathSum函数就可以达到原问题要求

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    int pathSum(TreeNode* root, int sum) {
        if (!root) return 0;

        vector<int> path;
        int cnt = 0;
        helper(root, sum, 0, path, cnt);
        return cnt + pathSum(root->left, sum) + pathSum(root->right, sum);
    }

    void helper(TreeNode* root, int sum, int out, vector<int>& path, int& cnt) {
        if (root) {
            path.push_back(root->val);
            out += root->val;
            if (out == sum) cnt++;

            helper(root->left, sum, out, path, cnt);
            helper(root->right, sum, out, path, cnt);

            path.pop_back();
        }
    }
};

看到每,pathSum 本身也是一个递归函数,它的返回值应该包括三部分,从当前结点出发找到的路径数量,从它的左右孩子出发找到的路径数量,这个地方确实需要一点技巧,就是本身是递归函数,然后其中又调用另外一个递归函数,和单纯的dfs形式上还是有点区别的。

posted @ 2021-02-02 22:16  nullxjx  阅读(82)  评论(0编辑  收藏  举报