leetcode:二叉树中和为某一值的路径

18 篇文章 0 订阅

题目来源:力扣

题目描述:

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

审题:

该题目为树搜索中的路径和问题.本题的复杂之处在于不单单是搜索符合要求的路径数量,而且是要打印出路径.本题的简单之处则在于对路径的定义:路径从根节点开始,且结束于叶节点.
考虑我们该如何打印出节点的路径呢?对于这道题,我一开始的设计是构建键值对,纪录每一节点的父节点,这样当我们搜索到符合要求的叶节点时,我们可沿叶节点的父节点一路向上回溯,直到根节点.关于该方法的实现后文会给出java代码.后来我看了其他人的题解,发现在此处使用键值对有点繁琐,增加了额外的空间复杂度与时间复杂度.考虑当前函数的递归调用自然而然的维护了从根节点到当前节点的一条路径.因此我们可在自上而下遍历节点的过程中,记录当前路径中的节点值,如果到达符合要求的叶节点处,我们将该条路径上的值复制,然后添加到总路径中即可.我们也给出这种算法的java代码.

java算法

方法一:
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    //使用键值对纪录当前节点的父节点
    Map<TreeNode, TreeNode> map = new HashMap<>();
    Stack<TreeNode> stack = new Stack<>();

    private void _pathSum(TreeNode x, int sum, int currentVal, List<List<Integer>> paths){
        if(x == null)
            return;
        if(x.val + currentVal == sum && x.left == null && x.right == null){
        	//如果当前找到一条路径,则回溯这条路径
            TreeNode cur = x;
            while(cur != null){
                stack.push(cur);
                cur = map.get(cur);
            }
            List<Integer> path = new LinkedList<>();
            while(!stack.isEmpty())
                path.add(stack.pop().val);
            paths.add(path);
        }
        if(x.left != null){
            map.put(x.left, x);
            _pathSum(x.left, sum, currentVal+x.val, paths);
        }
        if(x.right != null){
            map.put(x.right, x);
            _pathSum(x.right, sum, currentVal+x.val, paths);
        }
    }

    public List<List<Integer>> pathSum(TreeNode root, int sum) {
        map.put(root, null);
        List<List<Integer>> paths = new LinkedList<>();
        _pathSum(root, sum, 0, paths);
        return paths;
    }
}

方法二:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {

    //使用一个列表来保存当前函数递归调用栈上的节点值

    private void _pathSum(TreeNode x, int sum, List<Integer> currentPath, List<List<Integer>> paths){
        if(x == null)
            return;
        currentPath.add(x.val);
        sum -= x.val;
        if(sum == 0 && x.left == null && x.right == null){//如果当前找到一条路径
            List<Integer> path =  new ArrayList(currentPath);
            paths.add(path);
        }
        _pathSum(x.left, sum, currentPath, paths);
        _pathSum(x.right, sum, currentPath, paths);
        
        currentPath.remove(currentPath.size()-1); //移除最后一个元素,退栈;
        sum += x.val;  
        return;
    }

    public List<List<Integer>> pathSum(TreeNode root, int sum) {
        List<List<Integer>> paths = new LinkedList<>();
        List<Integer> currentPath = new LinkedList<>();
        _pathSum(root, sum, currentPath, paths);
        return paths;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值