二叉树系列之「二叉树中和为某一值的路径」

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

前置知识

如果节点为root,那么当前节点为叶子节点的必要条件是:

  • root.left == null && root.right == null

找出路径,当然需要遍历整棵树,遍历树的方式有很多种:前序、中序、后序,还有层序,这里选择前序遍历(根节点 --> 左子树 --> 右子树)。

具备了上述前置知识,这里无非增加了路径target以及叶子节点的判断。

涉及到树的遍历一般都是递归,既然是递归,那么一个大问题就可以分为子问题来求解,且子问题的解决方式与大问题相同。只需改变一些动态参数即可!

父子问题分析

这里以该问题为例,对父问题和子问题进行分析:

  • 这里的父问题就是给我一个二叉树,让我去求满足target的所有路径,而这个父问题又可以分为两个子问题(如果左右子节点皆存在的话)
  • 对于这个树的左子节点,那么问题就是,以该左子节点为根节点的左子树,求满足target-left.value的所有路径。
  • 以右子节点为根节点的右子树同理。

可以发现小问题可以和父问题共用一个函数进行求解,只不过参数的值是动态变化的而已。

递归算法三部曲

  1. 明白递归函数的功能。例如这里的FindPath(TreeNode root, int target),就是从根节点出发,找和为target的所有路径
  2. 递归终止条件。当root节点为叶子节点,并且target == root.val,表示找到了一条符合条件的路径
  3. 下一次递归。如果左子树不为空,则递归左子树FindPath(root.left, target-left.value),右子树同理

用两个全局变量保存路径。

Java实现如下

/**
public class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;

    public TreeNode(int val) {
        this.val = val;
    }
}
*/

public class Solution {
    private ArrayList<ArrayList<Integer>> result = new ArrayList<>();
    private ArrayList<Integer> list = new ArrayList<>();
  
    public ArrayList<ArrayList<Integer>> FindPath(TreeNode root, int target) {
        if(root == null) return result;
        list.add(root.val);
        target -= root.val; // 更新target
        if(target == 0 && root.left == null && root.right == null){ // target为0,且为叶子节点
          	result.add(new ArrayList<Integer>(list));
        }
        FindPath(root.left, target);
        FindPath(root.right, target);
        list.remove(list.size()-1);
        return result;
    }
}

如下图,为一个三层的二叉树,下面以该树为例,展示执行过程如下:
在这里插入图片描述
由于从始至终用的都是同一个list,最后的list.remove(list.size()-1); 语句的目的是每当判断一个节点,都会将其删除,这样,当结束时,list就是空的。

既然是同一个liist,那么每当找到一个路径,不能将同一个list添加到result中,所以

  • result.add(new ArrayList<Integer>(list));
  • 目的是新建一个ArrayList,将list中元素复制到ArrayList中,再将ArrayList添加到result
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值