0
点赞
收藏
分享

微信扫一扫

LeetCode刷题笔记 二叉树 路径总和

112 路径总和

给定一个二叉树root和一个值 sum ,判断是否有从根节点到叶子节点的节点值之和等于 sum 的路径。

输入一个二叉树和一个给定整数,输出一个布尔值,表示有没有条满足条件的路径。

解析:
注意叶子节点是指没有子节点的节点,路径只能从父节点到子节点,不能从子节点到父节点。

对于二叉树,任意给定节点到根节点之间的路径是唯一固定的。因此其对应的路径的总和也是唯一固定的。

因此,可利用前序方式对二叉树进行遍历,途中将每个节点中的val值替换成其对应的路径各vals之和。遍历过程中,检查leaf节点的val是否等于sum。

class Solution {
public:
    bool hasPathSum(TreeNode* root, int sum) {
        if(!root){
            return false;
        }
        // 判断是否是叶子节点
        if(!root->left && !root->right && root->val==sum){
            return true;
        }
        return hasPathSum(root->left, sum-root->val) || hasPathSum(root->right,sum-root->val);
    }
};

113 路径总和 II

给定一颗二叉树的根节点root和一个整数expectNumber,找出二叉树中结点值的和为目标值的所有路径。

输入一颗二叉树和一个整数,输出一个二维矩阵表示和为expectNumber的所有路径。

解析:

可以采用深度优先搜索的方式,枚举每一条从根节点到叶子节点的路径。

当遍历到叶子节点,且此时路径和恰为目标和时,我们就找到了一条满足条件的路径,将该路径加入结果集合。

class Solution {
public:
    void helper(TreeNode* root, int sum, vector<int>& path, vector<vector<int>>& paths){
        path.push_back(root->val);
        if(sum == root->val && !root->left && !root->right){
            paths.push_back(path);
        }
        if(root->left){
            helper(root->left,sum - root->val,path,paths);
        }
        if(root->right){
            helper(root->right, sum - root->val,path,paths);
        } 
        path.pop_back();
    }
    
    vector<vector<int>> FindPath(TreeNode* root,int expectNumber) {
        vector<vector<int>> paths;
        vector<int> path;
        if(!root){
            return paths;
        }
        helper(root,expectNumber,path,paths);
        return paths;
    }
};

437 路径总和 III

给定一个整数二叉树,求有多少条路径节点值的和等于给定值。

输入一个二叉树和一个给定整数,输出一个整数,表示有多少条满足条件的路径。

解析:

​ 本题的关键在于计算路径和,所以在递归每个节点时,需要分情况考虑:

  • 如果选取该节点加入路径,则之后必须继续加入连续节点,或停止加入节点
  • 如果不选取该节点加入路径,则对其左右节点进行重新进行考虑

​ 因此一个方便的方法是创建一个辅函数,专门用来计算连续加入节点的路径。该辅助函数就是通过用给定值递归减去路径节点值,最终给定值减为0表示构成一条路径。

class Solution {
public:
    int pathWithRoot(TreeNode* root, int sum){
        if(!root){
            return 0;
        }
        int count = 0;
        // 如果当前节点值与路径和一致则形成一条路径
        if(root->val == sum){
            count = 1;
        }else{
            count = 0;
        }
        // 往左右子节点继续寻找路径
        count += pathWithRoot(root->left, sum-root->val);
        count += pathWithRoot(root->right, sum-root->val);
        return count;
    }

    int pathSum(TreeNode* root, int targetSum) {
        if(!root){
            return 0;
        }
        // 将当前节点加入路径
        int ans = 0;
        ans = pathWithRoot(root,targetSum);
        // 不将当前节点加入路径,从左右子节点开始寻找新路径
        ans += pathSum(root->left,targetSum);
        ans += pathSum(root->right,targetSum);
        return ans;
    }
};

404 左叶子之和

给定一个二叉树,计算该树的所有左叶子之和

输入一颗二叉树,输出一个整数表示所有左叶子之和

解析:

​ 本题的关键就在于利用左叶子节点的定义进行有条件递归遍历二叉树,同时要判断一个节点是不是叶子节点,定义一个辅助函数如果该节点没有子节点则说明该节点是叶子节点。

​ 如果一个节点是左叶子节点,那么它是某个节点的左子节点,并且它还是一个叶子结点。

​ 根据此定义,在递归遍历过程中,如果一个节点有左子节点,且该节点是一个叶子节点,那么将该左子节点加到累和中;假若该左子节点不是叶子节点,则以该左子节点为根节点递归查找左叶子节点。

​ 如果一个节点有右子节点,且该节点是一个叶子节点,不进行累和且终止往下递归;假若该右子节点不是叶子节点,则将该右子节点为根节点递归查找左叶子节点。

class Solution {
public:
    bool isLeafNode(TreeNode* root){
        return  !root->left && !root->right;
    }

    int sumOfLeftLeaves(TreeNode* root) {
        if(!root){
            return 0;
        }
        int ans = 0;
        if(root->left){
            ans += isLeafNode(root->left)?root->left->val:sumOfLeftLeaves(root->left);
        }
        if(root->right){
            ans += isLeafNode(root->right)?0:sumOfLeftLeaves(root->right);
        }
        return ans;
    }
};

参考资料

LeetCode 101:和你一起轻松刷题(C++) 第 14 章 指针三剑客之树

举报

相关推荐

0 条评论