# 剑指 Offer 34. 二叉树中和为某一值的路径

1.题目

剑指 Offer 34. 二叉树中和为某一值的路径
输入一棵二叉树和一个整数,打印出二叉树中节点值的和为输入整数的所有路径。从树的根节点开始往下一直到叶节点所经过的节点形成一条路径。

 

示例:
给定如下二叉树,以及目标和 sum = 225
             / \
            4   8
           /   / \
          11  13  4
         /  \    / \
        7    2  5   1
返回:

[
   [5,4,11,2],
   [5,8,4,5]
]
 

提示:

节点总数 <= 10000

2.自我思路及实现

未AC
递归

DFS
递归
方法功能:获取树中和为某一值的路径中的所有节点
终止条件:节点为空
递归函数:子树sum = sum - 父节点值
当sum为零且左右子节点均为空时,表明找到了路径,将此路径存储起来
对左右子树进行递归

未实现的地方

  • 如何将每条路径上的节点存储起来
  • 如何存储多条路径
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
     
    public List<List<Integer>> pathSum(TreeNode root, int sum) {
        if(root== null)
            return new ArrayList<>();
        List<List<Integer>> res = new ArrayList<>();
        LinkedList<Integer> path = new LinkedList<>();
        dfs(root, sum, path);
        res.add(path);
        return res;
    }
    void dfs(TreeNode root, int sum, LinkedList<Integer> path)
    {
        if(root == null)
            return;
        sum -= root.val; 
        if(sum == 0 && root.left == null && root.right == null)
            path.add(root.val);

        dfs(root.left, sum, path);
        dfs(root.right, sum, path);

    }
}

3.总结思路及实现

DFS递归
使用成员变量二维动态数组res作为返回值,链表path存储路径,这样就可以在递归的过程中存储节点值和返回需要的路径

dfs方法功能:获取树中和为某一值的路径中的所有节点
终止条件:节点为空时返回
递归函数:
1.路径更新:将当前节点值加入路径path
2.目标值更新: sum -=root.val
3.路径记录:当sum为零且左右子节点均为空时,表明找到了路径,将此路径存入res,注意要新建一个路径来存储,否则后序操作会影响已存入的路径
4.先序遍历:递归左右子节点
5.路径恢复:向上回溯时,需要将当前节点从path中移除

时间:N2,在最坏情况下,树的上半部分为链状,下半部分为完全二叉树(除最后一层外其余各层节点数都达到最大个数),并且从根节点到每一个叶子节点的路径都符合题目要求。此时,路径的数目为 O(N),并且每一条路径的节点个数也为 O(N),因此要将这些路径全部添加进答案中,时间复杂度为 O(N^2)
空间:N,栈最大深度为N

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
     List<List<Integer>> res = new ArrayList<>();
     LinkedList<Integer> path = new LinkedList<>();
    public List<List<Integer>> pathSum(TreeNode root, int sum) {
        dfs(root, sum);
        return res;
    }
    void dfs(TreeNode root, int sum)
    {
        if(root == null)
            return;
        path.add(root.val);
        sum -= root.val;
        if(sum == 0 && root.left == null && root.right == null)
            res.add(new LinkedList<>(path));

        dfs(root.left, sum);
        dfs(root.right, sum);

        path.removeLast();
    }
}

BFS,队列实现
当遍历到叶子节点,且此时路径值恰为目标值时,获得一条满足要求的路径
使用哈希表存储节点与其父节点的对应关系
使用两个队列,一个队列存储节点,另一个队列存储该节点对应的路径上的所有节点值的和,当和==sum时且为叶子节点时,输出其路径

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    List<List<Integer>> res = new LinkedList<>();
    Map<TreeNode, TreeNode> map = new HashMap<>();
    public List<List<Integer>> pathSum(TreeNode root, int sum) {
        if(root == null)
            return res;
        
        Queue<TreeNode> nodeQue = new LinkedList<>(); //存储节点的队列
        Queue<Integer> curSum = new LinkedList<>();   //存储当前节点和值的队列
        nodeQue.offer(root);
        curSum.offer(0);

        while(!nodeQue.isEmpty())
        {
            TreeNode temp = nodeQue.poll();
            int cur = curSum.poll() + temp.val;
            if(cur == sum && temp.left == null && temp.right == null)
                path(temp);
            else
            {
                if(temp.left != null)
                {
                    nodeQue.offer(temp.left);
                    curSum.offer(cur);
                    map.put(temp.left, temp);
                }
                if(temp.right != null)
                {
                    nodeQue.offer(temp.right);
                    curSum.offer(cur);
                    map.put(temp.right, temp);
                }
            }
            
                
        }
        return res;

    }
    void path(TreeNode temp)
    {
        List<Integer> list = new LinkedList<>();
        while(temp != null)
        {
            list.add(temp.val);
            temp = map.get(temp);
        }
        Collections.reverse(list); //获得的路径是倒序的,需要反转
        res.add(new LinkedList<>(list));
    }
}

4.相关知识

  • 先将思路写下来,不要只想,一步一步确定
  • 树递归存储节点一般需要使用成员变量
  • public LinkedList(Collection<? extends E> c):将c中元素复制到新链表中
  • public ArrayList(Collection<? extends E> c):将c中元素复制到新动态数组中
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值