二叉树路径问题

这篇博客介绍了多种求解二叉树路径总和的方法,包括深度优先搜索(DFS)和广度优先搜索(BFS)。对于DFS,通过递归在到达叶子节点时检查路径和是否等于目标值。在BFS中,使用队列进行遍历。此外,还展示了记录多条路径、计算特定前缀和路径数量的解决方案,以及处理可能的溢出问题。这些算法都是在不断调整当前路径和并检查目标条件的同时,向下遍历二叉树节点。
摘要由CSDN通过智能技术生成

请添加图片描述

路经总和

DFS

深搜,如果搜到叶子结点时,此路径符合:找到;不符合:回溯
这里注意public boolean hasPathSum(TreeNode root, int targetSum) 此方法一开始传进来的就是sum,因此可以每往下走到下一结点,sum–,判断叶子结点处是否为0,而不是在根处sum=0,每次加结点值


class Solution {
    public boolean hasPathSum(TreeNode root, int targetSum) {
        //边界值
        if(root==null){
            return false;
        }
        //走到叶子结点的时候判断
        if(root.left==null && root.right==null){
            return targetSum-root.val==0;
        }
        //非叶子结点 左右 取并集
        return hasPathSum(root.left,targetSum-root.val) || hasPathSum(root.right,targetSum-root.val);
    }
}

BFS

解需要遍历二叉树,遍历考虑DFS BFS
BFS:使用队列


class Solution {
    public boolean hasPathSum(TreeNode root, int targetSum) {
        Queue<TreeNode>q = new LinkedList<TreeNode>();
        if(root!=null)
            q.add(root);
        TreeNode t;
        while(!q.isEmpty()){
            t = q.poll();
            if(t.left==null && t.right==null && t.val==targetSum){
                return true;
            } 
            if(t.left!=null){
                t.left.val += t.val;
                q.add(t.left);
            }
            if(t.right!=null){
                t.right.val += t.val;
                q.add(t.right);
            }
        }
        return false;
    }
}

113. 路径总和 II

记录路径

class Solution {
    List<List<Integer>> res = new ArrayList<List<Integer>>();
    List<Integer> path = new ArrayList<Integer>();
    public List<List<Integer>> pathSum(TreeNode root, int targetSum) {
        dfsPath(root,targetSum);
        return res;
    }
    public void dfsPath(TreeNode root,int targetSum){
        if(root==null){
            return ;
        }
        path.add(root.val); 
        targetSum -= root.val;
        if(root.left==null && root.right==null && targetSum==0){
            res.add(new ArrayList<Integer>(path));
        }
        dfsPath(root.left,targetSum);
        dfsPath(root.right,targetSum);
        //target不用加回来
        path.remove(path.size()-1); //很奇怪 用LinkedList的remoteLast不可以
    }
}



路径三

class Solution {
    Map<Integer,Integer>mp = new HashMap<>(); //mp[3] = 2 前缀和为2的路径总共有两条
    public int pathSum(TreeNode root, int targetSum) {
        mp.put(0,1);
       return dfs(root,0,targetSum);
    }
    public int dfs(TreeNode root,int curSum,int targetSum){
        if(root==null){
            return 0;
        }
        curSum += root.val; //走到当前节点 此时的前缀值
        //考虑之前走过的加上本节点  长度为当前前缀和目标值的差的路有多少条
        //当前结点是最后一个结点的情况
        int now = mp.getOrDefault(curSum-targetSum,0); 
        mp.put(curSum,mp.getOrDefault(curSum,0)+1); //当前前缀值是cursum 记录到mp中
        int left = dfs(root.left,curSum,targetSum);
        int right = dfs(root.right,curSum,targetSum);
        //状态恢复: 在遍历完一个节点的所有子节点后,将其从map中除去。
        //比如AB结点是root的左右孩子 遍历完A后 put进了A中有的前缀和 那么再遍历B时,能拿到A的前缀和 但是这不是从根节点一直往下得到的 因此要删掉
        mp.put(curSum,mp.get(curSum)-1); //当前前缀值是cursum 记录到mp中
        return now+left+right;

    }
}

注意超范围

class Solution {
    Map<Long,Long>mp = new HashMap<>(); //mp[3] = 2 前缀和为2的路径总共有两条
    public int pathSum(TreeNode root, int targetSum) {
       mp.put(0L,1L);
       return (int)(dfs(root,0L,targetSum));
    }
    public long dfs(TreeNode root,long curSum,long targetSum){
        if(root==null){
            return 0;
        }
        curSum += root.val; //走到当前节点 此时的前缀值
        //考虑之前走过的加上本节点  长度为当前前缀和目标值的差的路有多少条
        //当前结点是最后一个结点的情况
        Long now = mp.getOrDefault(curSum-targetSum,0L); 
        mp.put(curSum,mp.getOrDefault(curSum,0L)+1); //当前前缀值是cursum 记录到mp中
        long left = dfs(root.left,curSum,targetSum);
        long right = dfs(root.right,curSum,targetSum);
        //状态恢复: 在遍历完一个节点的所有子节点后,将其从map中除去。
        //比如AB结点是root的左右孩子 遍历完A后 put进了A中有的前缀和 那么再遍历B时,能拿到A的前缀和 但是这不是从根节点一直往下得到的 因此要删掉
        mp.put(curSum,mp.get(curSum)-1); //当前节点不影响其他兄弟结点 只影响其孩子结点
        return now+left+right;

    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值