LeetCode二叉树路径和专题:最大路径和与路径总和计数的策略

目录

437. 路径总和 III

深度优先遍历

前缀和优化

124. 二叉树中的最大路径和 


437. 路径总和 III

给定一个二叉树的根节点 root ,和一个整数 targetSum ,求该二叉树里节点值之和等于 targetSum 的 路径 的数目。

路径 不需要从根节点开始,也不需要在叶子节点结束,但是路径方向必须是向下的(只能从父节点到子节点)

示例 1:

输入:root = [10,5,-3,3,2,null,11,3,-2,null,1], targetSum = 8
输出:3
解释:和等于 8 的路径有 3 条,如图所示。

示例 2:

输入:root = [5,4,8,11,null,13,4,7,2,null,null,5,1], targetSum = 22
输出:3

提示:

  • 二叉树的节点个数的范围是 [0,1000]
  • -109 <= Node.val <= 109 
  • -1000 <= targetSum <= 1000 

深度优先遍历

遍历每个节点,以每个节点为根节点统计所有路径和为targetSum情况

class Solution {public int pathSum(TreeNode root, int targetSum) {if (root == null) {return 0;}int ret = rootSum(root, targetSum);ret += pathSum(root.left, targetSum);ret += pathSum(root.right, targetSum);return ret;}public int rootSum(TreeNode root, int targetSum) {int ret = 0;if (root == null) {return 0;}int val = root.val;if (val == targetSum) {ret++;} ret += rootSum(root.left, targetSum - val);ret += rootSum(root.right, targetSum - val);return ret;}
}

前缀和优化

解法一中应该存在许多重复计算,我们现在定义:前缀和是一个数列的每一项索引从0开始,表示从第0项到当前项的和。在这个问题中,我们将前缀和应用于二叉树的路径上,即从根节点到当前节点的所有节点值的和。

  1. 初始化:创建一个哈希表 prefix 来保存前缀和及其出现次数。为了处理从根节点开始的路径,我们提前在哈希表中设置前缀和0的计数为1。

  2. 递归遍历:使用深度优先搜索遍历二叉树。在每个节点处,计算从根节点到当前节点的前缀和。

  3. 查找当前路径和:检查当前的前缀和减去 targetSum 的结果是否在之前的路径中已经出现过,也就是检查 curr - targetSum 是否在哈希表 prefix 中。如果是,说明存在一个子路径的和等于 targetSum,将对应的次数添加到结果中。

  4. 更新哈希表:在访问节点之前,将当前前缀和的计数增加1,以表示这个前缀和现在被包含在路径中。

  5. 递归子节点:继续对左右子节点进行相同的处理。

  6. 回溯:在返回之前,需要将当前节点的前缀和的计数减1,因为当前节点即将被回溯,不应该计入其他路径(不存在以某个节点为根节点左右子树都存在的路径,所以要回溯避免影响其他路径)

class Solution {// 主函数public int pathSum(TreeNode root, int targetSum) {// 哈希表用于存储所有前缀和及其出现次数Map<Long, Integer> prefix = new HashMap<Long, Integer>();// 初始化:前缀和为0的路径有1条(空路径)prefix.put(0L, 1);// 开始深度优先搜索return dfs(root, prefix, 0, targetSum);}// 辅助函数:深度优先搜索public int dfs(TreeNode root, Map<Long, Integer> prefix, long curr, int targetSum) {// 如果当前节点为空,则返回0,表示没有路径if (root == null) {return 0;}int ret = 0; // 用于记录路径数curr += root.val; // 更新当前路径和// 查找当前路径和减去目标值的结果是否在前缀和中出现过// 出现过则表示找到了一条路径ret = prefix.getOrDefault(curr - targetSum, 0);// 更新前缀和中当前路径和的计数prefix.put(curr, prefix.getOrDefault(curr, 0) + 1);// 递归地搜索左子树和右子树,并累加路径数ret += dfs(root.left, prefix, curr, targetSum);ret += dfs(root.right, prefix, curr, targetSum);// 回溯:在返回之前,将当前节点的路径和的计数减1// 因为当前节点即将被回溯,不应该计入其他路径prefix.put(curr, prefix.getOrDefault(curr, 0) - 1);// 返回找到的路径总数return ret;}
}

让我们通过一个具体的例子来说明回溯在前缀和算法中的应用。假设有以下二叉树:

        10
       /  \
      5   -3
     / \    \
    3   2   11
   / \   \
  3  -2   1

并且我们要找的 targetSum 是8。我们将按照前缀和算法遍历这棵树。

  1. 开始于根节点 (10):

    • 当前前缀和: curr = 10
    • prefix = { (0,1) } (初始化,路径和为0出现了1次)
  2. 移动到左子节点 (5):

    • 当前前缀和: curr = 15
    • 更新前缀和计数: prefix = { (0,1), (15,1) }
  3. 继续到该节点的左子节点 (3):

    • 当前前缀和: curr = 18
    • 更新前缀和计数: prefix = { (0,1), (15,1), (18,1) }
  4. 进一步到该节点的左子节点 (3):

    • 当前前缀和: curr = 21
    • 更新前缀和计数: prefix = { (0,1), (15,1), (18,1), (21,1) }
  5. 回溯到节点 (3) 父节点 (3):

    • 我们完成了节点 (3) 的所有子节点的遍历
    • 当前前缀和: curr = 18
    • 回溯prefix = { (0,1), (15,1), (18,1) },移除之前节点 (3) 的前缀和
  6. 遍历节点 (3) 的右子节点 (-2):

    • 当前前缀和: curr = 16
    • 更新前缀和计数: prefix = { (0,1), (15,1), (18,1), (16,1) }
    • 回溯prefix = { (0,1), (15,1), (18,1) },完成节点 (-2) 的遍历,移除它的前缀和
  7. 回溯到节点 (5) 并转向它的右子节点 (2):

    • 我们完成了节点 (5) 的左子树的遍历
    • 当前前缀和: curr = 15
    • 回溯prefix = { (0,1), (15,1) },移除之前节点 (3) 和 (-2) 的前缀和
    • 当前前缀和: curr = 17 (添加节点 (2))
    • 更新前缀和计数: prefix = { (0,1), (15,1), (17,1) }
    • 检查17 (当前前缀和) - 8 (targetSum) = 9,在 prefix 中没有 9,所以没有发现新路径
    • 遍历节点 (2) 的左子节点 (1)
    • 当前前缀和: curr = 18 (添加节点 (1))
    • 更新前缀和计数: prefix = { (0,1), (15,1), (17,1), (18,1) }
    • 检查18 (当前前缀和) - 8 (targetSum) = 10,在 prefix 中有 10(根节点的值),所以我们找到了一条路径: 10 → 5 → 2 → 1
    • 回溯:完成节点 (1) 的遍历,回溯节点 (2)
  8. 最终回溯到根节点 (10) 并转向它的右子节点 (-3):

    • 当前前缀和: curr = 10
    • 回溯prefix = { (0,1) },移除左子树的前

124. 二叉树中的最大路径和 

二叉树中的 路径 被定义为一条节点序列,序列中每对相邻节点之间都存在一条边。同一个节点在一条路径序列中 至多出现一次 。该路径 至少包含一个 节点,且不一定经过根节点。

路径和 是路径中各节点值的总和。

给你一个二叉树的根节点 root ,返回其 最大路径和 。

示例 1:

输入:root = [1,2,3]
输出:6
解释:最优路径是 2 -> 1 -> 3 ,路径和为 2 + 1 + 3 = 6

示例 2:

输入:root = [-10,9,20,null,null,15,7]
输出:42
解释:最优路径是 15 -> 20 -> 7 ,路径和为 15 + 20 + 7 = 42

提示:

  • 树中节点数目范围是 [1, 3 * 104]
  • -1000 <= Node.val <= 1000
class Solution {int maxSum = Integer.MIN_VALUE;public int maxPathSum(TreeNode root) {maxGain(root);return maxSum;}public int maxGain(TreeNode node) {if (node == null) {return 0;}// 递归计算左右子节点的最大贡献值// 只有在最大贡献值大于 0 时,才会选取对应子节点int leftGain = Math.max(maxGain(node.left), 0);int rightGain = Math.max(maxGain(node.right), 0);// 节点的最大路径和取决于该节点的值与该节点的左右子节点的最大贡献值int priceNewpath = node.val + leftGain + rightGain;// 更新答案maxSum = Math.max(maxSum, priceNewpath);// 返回节点的最大贡献值return node.val + Math.max(leftGain, rightGain);}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/590251.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

简单FTP客户端软件开发——VMware安装Linux虚拟机(命令行版)

VMware安装包和Linux系统镜像&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1UwF4DT8hNXp_cV0NpSfTww?pwdxnoh 提取码&#xff1a;xnoh 这个学期做计网课程设计【简单FTP客户端软件开发】需要在Linux上配置 ftp服务器&#xff0c;故此用VMware安装了Linux虚拟机&…

<软考高项备考>《论文专题 - 39采购管理(3) 》

3 过程2-实施采购 3.1 问题 4W1H过程做什么获取卖方应答、选择卖方并授予合同的过程作用&#xff1a;选定合格卖方并签署关于货物或服务交付的法律协议。本过程的最后成果是签订的协议&#xff0c;包括正式合同。为什么做实际进行采购谁来做组织中的职能部门或项目经理什么时…

遭遇.360、.halo勒索病毒:应对.360、.halo勒索病毒的最佳方法

尊敬的读者&#xff1a; 在数字时代的今天&#xff0c;科技的飞速发展为我们的工作和生活带来了便捷&#xff0c;然而&#xff0c;与此同时&#xff0c;网络空间中的威胁也日益猖獗。其中之一的勒索病毒&#xff0c;如.360、.halo病毒&#xff0c;以其高度隐蔽和破坏性成为网络…

burpsuite模块介绍之compare

导语 Burp Comparer是Burp Suite中的一个工具&#xff0c;主要提供一个可视化的差异比对功能&#xff0c;可以用于分析比较两次数据之间的区别。它的应用场景包括但不限于&#xff1a; 枚举用户名过程中&#xff0c;对比分析登陆成功和失败时&#xff0c;服务器端反馈结果的区…

编程式导航传参

(通过js代码实现跳转) 按照path进行跳转 第一步&#xff1a; 在app.vue中(前提是规则已经配置好) <template><div id"app">App组件<button clicklogin>跳转</button><!--路由出口-将来匹配的组件渲染地方--><router-view>&l…

【嵌入式学习笔记-01】什么是UC,操作系统历史介绍,计算机系统分层,环境变量(PATH),错误

【嵌入式学习笔记】什么是UC&#xff0c;操作系统历史介绍&#xff0c;计算机系统分层&#xff0c;环境变量&#xff08;PATH&#xff09;&#xff0c;错误 文章目录 什么是UC?计算机系统分层什么是操作系统&#xff1f; 环境变量什么是环境变量&#xff1f;环境变量的添加&am…

一次降低进程IO延迟的性能优化实践——基于block层bfq调度器(下篇)

在上一篇《一次降低进程IO延迟的性能优化实践——基于block层bfq调度器》基础上&#xff0c;本文主要总结实现该IO性能优化过程遇到的 IO卡死、IO重复派发、内核crash等问题。 1&#xff1a;IO重复派发触发了crash 在初版代码编写完成后&#xff0c;启动fio测试cat读取文件&a…

简写英语单词

题目&#xff1a; 思路&#xff1a; 这段代码的主要思路是读取一个字符串&#xff0c;然后将其中每个单词的首字母大写输出。具体来说&#xff0c;程序首先使用 fgets 函数读取一个字符串&#xff0c;然后遍历该字符串中的每个字符。当程序遇到一个字母时&#xff0c;如果此时…

在Linux中进行ZooKeeper集群搭建

在公网IP为x.x.x.x、y.y.y.y和z.z.z.z并装有Alibaba Cloud Linux 3.2104 LTS 64位的服务器上进行zookeeper集群搭建&#xff0c;都安装server-jre-8u202-linux-x64和apache-zookeeper-3.9.1-bin。 环境准备&#xff08;三台服务器都一样&#xff09; 第一步&#xff0c;下载s…

基于图论的图像分割 python + PyQt5

数据结构大作业&#xff0c;基于图论中的最小生成树的图像分割。一个很古老的算法&#xff0c;精度远远不如深度学习算法&#xff0c;但是对于代码能力是一个很好的锻炼。 课设要求&#xff1a; &#xff08; 1 &#xff09;输入&#xff1a;图像&#xff08;例如教室场景图&a…

四、Spring IoC实践和应用(三种配置方式总结)

本章概要 三种配置方式总结 XML方式配置总结XML注解方式配置总结完全注解方式配置总结 整合Spring5-Test5搭建测试环境 4.5 三种配置方式总结 4.5.1 XML方式配置总结 所有内容写到xml格式配置文件中声明bean通过<bean标签<bean标签包含基本信息&#xff08;id,class&…

字符串拼接 (90%用例)C卷 (JavaPythonNode.jsC++)

给定M(0<M<=30)个字符 (a-z),从中取出任意字符 (每个字符只能用一次)拼接成长度为N(0<N<=5)的字符串,要求相同的字符不能相邻,计算出给定的字符列表能拼接出多少种满足条件的字符串,输入非法或者无法拼接出满足条件的字符串则返回0。 输入描述 给定的字符列表…

47、激活函数 - sigmoid

今天在看一个比较常见的激活函数,叫作 sigmoid 激活函数,它的数学表达式为: 其中,x 为输入,画出图来看更直观一些。 Sigmoid 函数的图像看起来像一个 S 形曲线,我们先分析一下这个函数的特点。 Sigmoid 函数的输出范围在 (0, 1) 之间,并且不等于0或1。 Sigmoid 很明显是…

Codeforces Round 900 (Div. 3)(A-F)

比赛链接 : Dashboard - Codeforces Round 900 (Div. 3) - Codeforces A. How Much Does Daytona Cost? 题面 : 思路 : 在序列中只要找到k&#xff0c;就返回true ; 代码 : #include<bits/stdc.h> #define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)…

客户端和驱动程序

今天我们来聊聊数据库领域中经常出现的两个术语&#xff1a;客户端和驱动程序。 客户端和驱动程序 客户端&#xff1a; 通常是指使用数据库服务的应用程序或工具。这可能是一个图形用户界面(GUI)工具、命令行工具、Web应用程序或其他形式的应用程序。客户端负责发起数据库请…

spring 之 事务

1、JdbcTemplate Spring 框架对 JDBC 进行封装&#xff0c;使用 JdbcTemplate 方便实现对数据库操作 1.1 准备工作 ①搭建子模块 搭建子模块&#xff1a;spring-jdbc-tx ②加入依赖 <dependencies><!--spring jdbc Spring 持久化层支持jar包--><dependency&…

基于SpringBoot的在线互动学习网站

文章目录 项目介绍主要功能截图:部分代码展示设计总结项目获取方式🍅 作者主页:超级无敌暴龙战士塔塔开 🍅 简介:Java领域优质创作者🏆、 简历模板、学习资料、面试题库【关注我,都给你】 🍅文末获取源码联系🍅 项目介绍 基于SpringBoot的在线互动学习网站,java…

工程类标书制作攻略

工程类标书是工程项目中非常重要的一环&#xff0c;它不仅反映了投标者的技术实力和经验&#xff0c;更是决定项目归属的关键因素。那么&#xff0c;如何制作一份高质量的工程类标书呢&#xff1f; 一、明确招标要求 在制作标书前&#xff0c;首先要仔细阅读招标文件&#xf…

性能优化(CPU优化技术)-ARM Neon详细介绍

本文主要介绍ARM Neon技术&#xff0c;包括SIMD技术、SIMT、ARM Neon的指令、寄存器、意图为读者提供对ARM Neon的一个整体理解。 &#x1f3ac;个人简介&#xff1a;一个全栈工程师的升级之路&#xff01; &#x1f4cb;个人专栏&#xff1a;高性能&#xff08;HPC&#xff09…

2024年总结的前端学习路线分享(学习导读)

勤学如春起之苗&#xff0c;不见其增&#xff0c;日有所长 。辍学如磨刀之石&#xff0c;不见其损&#xff0c;日有所亏。 在写上一篇 2023年前端学习路线 的时候&#xff0c;时间还在2023年初停留&#xff0c;而如今不知不觉时间已经悄然来到了2024年&#xff0c;回顾往昔岁月…