【牛客 - 剑指offer】JZ84 二叉树中和为某一值的路径(三)


剑指offer题解汇总 Java实现

https://blog.csdn.net/guliguliguliguli/article/details/126089434

本题链接

知识分类篇 - 树 - JZ84 二叉树中和为某一值的路径(三)

题目

在这里插入图片描述

解决方案

方案一 深度优先搜索 dfs

dfs思路

二叉树递归
递归是一个过程或函数,在其定义或说明中有直接或简介调用自身的一种方法,它通常把大型、复杂的问题层层转化为一个与原问题相似的、规模较小的问题来求解。因此递归过程,最重要的就是查看能不能将原问题分解为更小的子问题,这是使用递归的关键。

二叉树的递归,则是将某个节点的左子树、右子树看成一颗完整的树,那么对于子树的访问或者操作就是对于原树的访问或者操作的子问题,因此可以自我调用函数,不断进入子树。

思路

  • 既然要找所有路径上节点和等于目标值的路径个数,那首先,得找到起点。题目中不要求一定要从根节点开始,也不要求一定要在叶子节点结束,所以任意起点都有可能成为起点,可以使用前序遍历遍历二叉树的所有节点,每个节点都可以作为一次起点,即子树的根节点。
FindPath(root.left, sum);
FindPath(root.right,sum);
  • 查找路径的时候,需要往下遍历,因此还是按照前序遍历的方式遍历该子树,在遍历过程中遇到一个节点,sum相应的减少,若往下的一个节点值正好等于剩下的sum,则找到了个情况
dfs(root.left, sum-root.val);
dfs(root.right, sum-root.val);
  • FindPath()方法用于遍历所有节点,让其作为根节点,检查是否有合适的路径

  • dfs()方法,针对于每一个子树,检查以该节点为根的子树上是否有满足条件的

代码

import java.util.*;

/*
 * public class TreeNode {
 *   int val = 0;
 *   TreeNode left = null;
 *   TreeNode right = null;
 *   public TreeNode(int val) {
 *     this.val = val;
 *   }
 * }
 */

public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * @param root TreeNode类
     * @param sum  int整型
     * @return int整型
     */
    private int res = 0;

    public int FindPath(TreeNode root, int sum) {
        // write code here
        if (root == null) {
            return res;
        }
        //查询以某节点为根的路径数
        dfs(root, sum);

        //以其子节点为新根
        FindPath(root.left, sum);
        FindPath(root.right, sum);
        return res;
    }


    //dfs查询以某节点为根的路径数
    public void dfs(TreeNode root, int sum) {
        if (root == null) {
            return;
        }
        if (sum == root.val) {
            //System.out.println("root.val" + root.val);
            res++;
        }
        dfs(root.left, sum - root.val);
        dfs(root.right, sum - root.val);
    }
}

dfs个人总结

我自己认为,dfs的代码比较难写,但是在看到答案以后又觉得很简单,真正调试起来一层一层的递归,看得头都大了,所以应对dfs最好的方法就是Debug,可以把递归过程看得很清楚,有时侯,手速快了点,断点少了点,就跳过去了,那就从头再Debug一遍吧,Debug的断点我建议尽可能多打,这样能避免错过一些重要的过程

方案二 哈希表 HashMap

哈希表思路

在这里插入图片描述

哈希表是一种根据关键码(key)直接访问值(value)的一种数据结构。而这种直接访问意味着key能在O(1)的时间内找到value,因此哈希表常用来统计频率、快速检验某个元素是否出现过等。

上面的dfs思路每一个节点都要作为子树,按照前序遍历的顺序遍历一次,有的节点有被重复计算

在进入以某个节点为根的子树中,向其中添加到该节点为止的路径,和进入哈希表中,相当于每次分支下都有前面各种路径和。

如果从根节点开始到当前节点的累加和减去sum,在哈希表中出现过,则说明这条路径上前半段和等于到当前节点的累加和减去sum,

代码

import java.util.*;
public class Solution {
    //记录路径和及条数
    private HashMap<Integer, Integer> mp = new HashMap<Integer, Integer>();
    //last为到上一层为止的累加和
    private int dfs(TreeNode root, int sum, int last){
        //空结点直接返回
        if(root == null)
            return 0;
        int res = 0;
        //到目前结点为止的累加和
        int temp = root.val + last;
		//如果该累加和减去sum在哈希表中出现过,相当于减去前面的分支
		if(mp.containsKey(temp - sum))
		    //加上有的路径数
		    res += mp.get(temp - sum);
        //增加该次路径和
        mp.put(temp, mp.getOrDefault(temp, 0) + 1);
        //进入子结点
        res += dfs(root.left, sum, temp);
        res += dfs(root.right, sum, temp);
        //回退该路径和,因为别的树枝不需要这边存的路径和
        mp.put(temp, mp.get(temp) - 1);
        return res;
    }

    public int FindPath (TreeNode root, int sum) {
        //路径和为0的有1条
        mp.put(0, 1);
        return dfs(root, sum, 0);
    }
}

个人总结

虽然方案一的效率没有方案二高,但是方案一比较容易理解,方案二中,我认为,比较关键的代码是:

//如果该累加和减去sum在哈希表中出现过,相当于减去前面的分支
if(mp.containsKey(temp - sum))
    //加上有的路径数
    res += mp.get(temp - sum);

在遍历 1 2 5 -1 这条线的时候,temp=7,但是除去根节点1以后,就是我们要找的满足条件的一条路线,所以,如果map中存在一条,前面路径和是1的路径,则结果计数就可以+1

我这么说感觉也很苍白无力,需要自己动手debug一下,就比较清楚了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
题目要求:给定一个二叉树和一个整数target,找出所有从根节点到叶子节点路径之和等于target的路径。 解题思路:可以使用深度优先搜索(DFS)的方法来解决该问题。首先定义一个辅助函数来进行递归搜索,该辅助函数的参数包括当前节点、当前路径、当前路径的和以及目标和。在搜索过程中,需要维护一个数组来保存当前节点到根节点的路径。搜索过程如下: 1. 如果当前节点为空,则返回。 2. 将当前节点的添加到当前路径中。 3. 将当前节点的累加到当前路径的和中。 4. 如果当前节点是叶子节点,且当前路径的和等于目标和,则将当前路径添加到结果中。 5. 递归地搜索当前节点的左子树和右子树,并传递更新后的当前路径和当前路径的和。 最后,在主函数中调用辅助函数,并返回结果即可。 以下是题目的完整代码实现: ```python class TreeNode: def __init__(self, val=0, left=None, right=None): self.val = val self.left = left self.right = right def pathSum(root, target): def dfs(node, path, path_sum, target, res): if not node: return path.append(node.val) path_sum += node.val if not node.left and not node.right: # 当前节点是叶子节点 if path_sum == target: res.append(path[:]) # 注意需要复制一份path,否则会出现问题 dfs(node.left, path, path_sum, target, res) dfs(node.right, path, path_sum, target, res) path.pop() # 回溯到父节点,去掉当前节点 path_sum -= node.val res = [] dfs(root, [], 0, target, res) return res ``` 这样就能找出所有满足路径和等于目标和的路径了。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值