二叉树之路径总和

路径总和

给你二叉树的根节点 root 和一个表示目标和的整数 targetSum 。判断该树中是否存在根节点到叶子节点的路径,这条路径上所有节点值相加等于目标和 targetSum 。如果存在,返回 true ;否则,返回 false 。叶子节点是指没有子节点的节点。

示例 1:在这里插入图片描述
注图片转载自leetcode官网
输入:root = [5,4,8,11,null,13,4,7,2,null,null,null,1], targetSum = 22
输出:true
解释:等于目标和的根节点到叶节点路径如上图所示。

class Solution {
    int sum = 0;
    public boolean hasPathSum(TreeNode root, int targetSum) {
        if(root == null) return false;
        sum += root.val;
        if(sum == targetSum && root.left == null && root.right == null) return true;
        boolean leftVal = hasPathSum(root.left, targetSum);
        boolean rightVal = hasPathSum(root.right, targetSum);
        sum -= root.val;
        return leftVal || rightVal;
    }
}

路径总和II

给你二叉树的根节点 root 和一个整数目标和 targetSum ,找出所有从根节点到叶子节点路径总和等于给定目标和的路径。叶子节点是指没有子节点的节点。

示例 1:
在这里插入图片描述
注图片转载自leetcode官网
输入:root = [5,4,8,11,null,13,4,7,2,null,null,5,1], targetSum = 22
输出:[[5,4,11,2],[5,8,4,5]]

class Solution {
    List<List<Integer>> ans;
    public List<List<Integer>> pathSum(TreeNode root, int targetSum) {
        ans = new ArrayList<>();
        List<Integer> list = new ArrayList<>();
        int sum = 0;
        tarversal(root, targetSum, list, sum);
        return ans;
    }
    private void tarversal(TreeNode root, int targetSum, List<Integer> list, int sum){
        if(root == null) return;
        sum += root.val;
        list.add(root.val);
        if(root.left == null && root.right == null){
            if(sum == targetSum){
                ans.add(new ArrayList<>(list));
            }
        }
        tarversal(root.left, targetSum, list, sum);
        tarversal(root.right, targetSum, list, sum);
        sum -= root.val;
        list.remove(list.size() - 1);
    }
}

        与上一题相比,这题要求找到所有从根结点到叶子结点路径总和等于targetSum的路径,而上一题仅找出一条即可。这里详细说明上述代码的执行流程。首先定义一个list集合用于收集某条路径上的结点,sum用于记录对应路径的和。对应的结点的左右子树遍历完成后,将对应结点从list集合移除,sum减去对应结点的值,即为回溯的过程。
        接着进入tarversal方法。首先遍历根结点5,之后sum += 5,sum等于5,将根结点5的值放入list集合中,list为[5]。接着if判断根结点是否为叶子结点,显然不为叶子结点,递归进入根结点的left,sum += 4,sum等于9,将结点4加入list集合中,list为[5, 4]。接着if判断结点4是否为叶子结点,显然不为叶子结点,递归进入结点4的left,sum += 11,sum等于20,将结点11加入list集合中,list为[5, 4, 11]。接着if判断结点11是否为叶子结点,显然不为叶子结点,递归进入结点11的left,sum += 7,sum为27,将7加入list集合中,list为[5, 4, 11, 7],之后if判断结点7是否为叶子结点,显然结点7为叶子结点,但是sum不等于targetSum(22),继续递归进入结点7的left,因为结点7的left为空,递归返回,递归进入结点7的right,right为空,递归返回,结点7左右子树遍历完成,sum -= 7,sum为20,将结点7从list集合中移除,list为[5, 4, 11]。递归返回,并进入结点11的right,将sum += 2,sum为22,将结点2加入list集合,list集合为[5, 4, 11, 2],接着if判断结点2是否为叶子结点,显然结点2为叶子结点,并且此时sum等于targetSum,重新创建一个集合将list中的所有值传入该集合,并放入ans中。递归进入结点2的left,为空,返回,递归进入结点2的right,为空,返回,结点2的左右子树遍历完成,sum -= 2,sum为20,将结点2从list中移除,list为[5, 4, 11]。递归返回结点11,结点11的左右子树遍历完成,将sum -= 11,sum为9,将结点11从list集合中移除,list为[5, 4]。递归返回结点4,进入结点4的right,为空,返回。结点4的左右子树遍历完成,sum -= 4,sum等于5,将结点4从list集合中移除,list为[5]。递归返回根结点5,此时根结点5的左子树遍历完成,按上述过程继续递归根结点的右子树,就可以得到路径和等于targetSum的所有路径。

路径总和III

给定一个二叉树的根节点 root ,和一个整数 targetSum ,求该二叉树里节点值之和等于 targetSum 的路径的数目。路径不需要从根节点开始,也不需要在叶子节点结束,但是路径方向必须是向下的(只能从父节点到子节点)。

示例 1:
在这里插入图片描述
注图片转载自leetcode官网
输入:root = [10,5,-3,3,2,null,11,3,-2,null,1], targetSum = 8
输出:3
解释:和等于 8 的路径有 3 条,如图所示。

class Solution {
    int ans = 0;
    public int pathSum(TreeNode root, int targetSum) {
        tarversal(root, targetSum);
        return ans;
    }
    private void tarversal(TreeNode root, long targetSum){
        if(root == null) return;
        tarverSum(root, targetSum);
        tarversal(root.left, targetSum);
        tarversal(root.right, targetSum);
    }
    private void tarverSum(TreeNode root, long targetSum){
        if(root == null) return;
        targetSum -= root.val;
        if(targetSum == 0){
            ans++;
        }
        tarverSum(root.left, targetSum);
        tarverSum(root.right, targetSum);
    }
}

        之前的两道题要求路径必须从根结点出发,到叶子结点,而这道题,可以是根结点到叶子结点的其中一段路径,不一定要从根结点出发,不一定以叶子结点作为尾结点。这题的解题思路就是遍历所有结点,将每个结点都作为根结点,在tarversal方法中,采用前序遍历的方式遍历所有结点,每次将每个结点作为根结点,调用tarverSum方法,将当前结点和targetSum传入tarverSum方法中。在tarverSum方法中,以当前传入结点作为起始结点,采用前序遍历的方式,每次targetSum减去遍历到的结点值,如果targetSum的值为0时,表示存在一条路径。
        下面详细描述上述代码的执行过程。首先tarversal方法中遍历根结点,将根结点10以及targetSum(8)传入tarverSum方法中。在tarverSum中,tarverSum -= 10,tarverSum等于-2,不为0,接着遍历结点10的left,将-2传入tarverSum中,tarverSum -=5,tarverSum = -7,不为0,接着遍历结点5的left,将-7传入tarverSum中,tarverSum -= 3,tarverSum = -10,不为0,接着遍历结点3的left,将-10传入tarverSum中,tarverSum -= 3,tarverSum = -13,不为0,接着遍历结点3的left,为空返回,接着遍历结点3的right,为空返回。结点3的左右子树遍历完成,递归返回上一个结点3,继续上一个结点3的right,将-10传入tarverSum中,tarverSum -= -2,tarverSum等于-12,不为0,接着递归结点-2的left,为空返回,接着遍历结点-2的right,为空返回。结点-2的左右子树遍历完成,递归返回结点-3。-3的左右子树遍历完成,递归返回结点5。递归进入结点5的right,将-7传入tarverSum中,如此重复上述过程,即可完成以结点10为根结点的所有路径的遍历。
        之后以5, 3, 3, -2…为分别为根结点重复上述过程,即可找到所有路径和为targetSum的路径数。

相关推荐

  1. 路径总和系列问题

    2024-05-04 19:58:05       42 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-05-04 19:58:05       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-05-04 19:58:05       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-05-04 19:58:05       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-05-04 19:58:05       18 阅读

热门阅读

  1. 力扣简单题 392.1491.509

    2024-05-04 19:58:05       12 阅读
  2. 字符串哈希-最易懂的证明

    2024-05-04 19:58:05       8 阅读
  3. Linux下运行jar包的方式

    2024-05-04 19:58:05       10 阅读
  4. MongoDB聚合运算符:$tan

    2024-05-04 19:58:05       8 阅读
  5. Spring MVC系列之异步请求

    2024-05-04 19:58:05       7 阅读