二叉树题目:路径总和 III

news2024/11/18 16:54:55

文章目录

  • 题目
    • 标题和出处
    • 难度
    • 题目描述
      • 要求
      • 示例
      • 数据范围
  • 解法一
    • 思路和算法
    • 代码
    • 复杂度分析
  • 解法二
    • 思路和算法
    • 代码
    • 复杂度分析

题目

标题和出处

标题:路径总和 III

出处:437. 路径总和 III

难度

5 级

题目描述

要求

给你二叉树的根结点 root \texttt{root} root 和一个表示目标和的整数 targetSum \texttt{targetSum} targetSum,返回结点值总和等于目标和 targetSum \texttt{targetSum} targetSum 的路径的数目。

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

示例

示例 1:

示例 1

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

示例 2:

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

数据范围

  • 树中结点数目在范围 [0,   1000] \texttt{[0, 1000]} [0, 1000]
  • -10 9 ≤ Node.val ≤ 10 9 \texttt{-10}^\texttt{9} \le \texttt{Node.val} \le \texttt{10}^\texttt{9} -109Node.val109
  • -1000 ≤ targetSum ≤ 1000 \texttt{-1000} \le \texttt{targetSum} \le \texttt{1000} -1000targetSum1000

解法一

思路和算法

定义路径的开始结点是路径中的层数最小(即和根结点距离最小)的结点,结束结点是路径中的层数最大(即和根结点距离最大)的结点。

如果二叉树为空,则不存在结点值总和等于目标和的路径,返回 0 0 0

当二叉树不为空时,遍历二叉树中的每个结点,分别将每个结点作为开始结点,寻找所有结点值总和等于目标和的路径。寻找路径的做法是,在开始结点为根结点的子树中深度优先搜索,假设开始结点值为 val \textit{val} val,则对于开始结点的每个非空子树,子树中的每一条结点值总和等于 targetSum − val \textit{targetSum} - \textit{val} targetSumval 的路径都对应从开始结点出发的一条结点值总和等于 targetSum \textit{targetSum} targetSum 的路径。

由于计算非空子树中的结点值总和等于特定值的路径数目可以使用同样的方法,因此计算路径数目的过程是一个递归的过程。递归的终止条件是二叉树为空,此时路径数目是 0 0 0。对于其余情况,执行如下操作。

  1. 如果根结点值等于目标和,则以根结点为结束结点的路径为结点值总和等于目标和的路径,将路径数目加 1 1 1;如果根结点值不等于目标和,则路径数目不变。

  2. 对左子树和右子树递归地计算路径数目。

代码

class Solution {
    public int pathSum(TreeNode root, int targetSum) {
        if (root == null) {
            return 0;
        }
        int count = countPaths(root, targetSum);
        count += pathSum(root.left, targetSum);
        count += pathSum(root.right, targetSum);
        return count;
    }

    public int countPaths(TreeNode node, long targetSum) {
        if (node == null) {
            return 0;
        }
        int count = 0;
        if (node.val == targetSum) {
            count++;
        }
        count += countPaths(node.left, targetSum - node.val);
        count += countPaths(node.right, targetSum - node.val);
        return count;
    }
}

复杂度分析

  • 时间复杂度: O ( n 2 ) O(n^2) O(n2),其中 n n n 是二叉树的结点数。需要对每个结点计算路径数目,每个结点需要 O ( n ) O(n) O(n) 的时间计算路径数目,因此总时间复杂度是 O ( n 2 ) O(n^2) O(n2)

  • 空间复杂度: O ( n ) O(n) O(n),其中 n n n 是二叉树的结点数。空间复杂度主要是递归调用的栈空间,取决于二叉树的高度,最坏情况下二叉树的高度是 O ( n ) O(n) O(n)

解法二

思路和算法

解法一存在重复计算,因此时间复杂度较高。如果可以存储已经计算过的结果,则可以避免重复计算,降低时间复杂度。

假设从根结点到结点 node 1 \textit{node}_1 node1 的路径上的结点值总和为 sum 1 \textit{sum}_1 sum1,在同一条路径上存在不同于结点 node 1 \textit{node}_1 node1 的结点 node 2 \textit{node}_2 node2,从根结点到结点 node 2 \textit{node}_2 node2 的路径上的结点值总和为 sum 2 \textit{sum}_2 sum2,则该路径上从结点 node 2 \textit{node}_2 node2 的子结点到结点 node 1 \textit{node}_1 node1 的子路径(注意子路径包含 node 1 \textit{node}_1 node1,不包含结点 node 2 \textit{node}_2 node2)上的结点值总和为 sum 1 − sum 2 \textit{sum}_1 - \textit{sum}_2 sum1sum2。如果 sum 1 − sum 2 = targetSum \textit{sum}_1 - \textit{sum}_2 = \textit{targetSum} sum1sum2=targetSum,则找到一条结点值总和等于 targetSum \textit{targetSum} targetSum 的路径。

基于上述分析,可以记录从根结点出发的路径中的每个结点值总和的出现次数,达到优化时间复杂度的目的。以下将从根结点出发的路径中的每个结点值总和称为「根路径和」。

从根结点开始深度优先搜索,使用哈希表记录每个根路径和的出现次数。对于每一条从根结点出发的路径,按照层数递增的顺序依次访问每个结点,访问每个结点时更新当前结点的根路径和,并在哈希表中将当前结点的根路径和的出现次数加 1 1 1。对于访问到的每个结点,如果当前结点的根路径和为 sum \textit{sum} sum,则从哈希表中得到根路径和 sum − targetSum \textit{sum} - \textit{targetSum} sumtargetSum 的出现次数,该出现次数即为以当前结点为结束结点的结点值总和等于 targetSum \textit{targetSum} targetSum 的路径数目。在访问当前结点之后,继续访问当前结点的非空结点。

实现方面有两点需要注意。

  • 由于结点值总和等于 targetSum \textit{targetSum} targetSum 的路径可能从根结点出发,因此需要预处理空路径,空路径的结点值总和等于 0 0 0,在搜索之前将根路径和 0 0 0 出现 1 1 1 次存入哈希表。

  • 深度优先搜索的过程中,当访问完一个子树并退出该子树时,需要撤销对根路径和以及哈希表的更新,避免当前子树的根路径和信息对其他子树的结果造成影响。

代码

class Solution {
    Map<Long, Integer> sumCountMap = new HashMap<Long, Integer>();

    public int pathSum(TreeNode root, int targetSum) {
        if (root == null) {
            return 0;
        }
        sumCountMap.put(0L, 1);
        return getCounts(root, root.val, targetSum);
    }

    public int getCounts(TreeNode node, long sum, int targetSum) {
        int count = sumCountMap.getOrDefault(sum - targetSum, 0);
        sumCountMap.put(sum, sumCountMap.getOrDefault(sum, 0) + 1);
        TreeNode left = node.left, right = node.right;
        if (left != null) {
            count += getCounts(left, sum + left.val, targetSum);
        }
        if (right != null) {
            count += getCounts(right, sum + right.val, targetSum);
        }
        sumCountMap.put(sum, sumCountMap.get(sum) - 1);
        return count;
    }
}

复杂度分析

  • 时间复杂度: O ( n ) O(n) O(n),其中 n n n 是二叉树的结点数。每个结点都被访问一次。

  • 空间复杂度: O ( n ) O(n) O(n),其中 n n n 是二叉树的结点数。空间复杂度主要是递归调用的栈空间以及哈希表空间,取决于二叉树的高度,最坏情况下二叉树的高度是 O ( n ) O(n) O(n)

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

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

相关文章

VS2022 打包WPF安装程序最新教程(图文详解)

文章目录 前言一、安装打包Installer插件1、单独安装2、VS中在线安装二、使用步骤1、创建安装项目2、安装项目主界面3、添加项目输出4、添加快捷方式图标5、添加卸载项目a、新建项目b、添加项目输出c、创建快捷方式6、给快捷方式添加图标a、在Resource文件夹中添加图标文件b、选…

通过内网穿透实现在无公网IP下,Windows远程连接MongoDB数据库

文章目录 前言1. 安装数据库2. 内网穿透2.1 安装cpolar内网穿透2.2 创建隧道映射2.3 测试随机公网地址远程连接 3. 配置固定TCP端口地址3.1 保留一个固定的公网TCP端口地址3.2 配置固定公网TCP端口地址3.3 测试固定地址公网远程访问 前言 MongoDB是一个基于分布式文件存储的数…

shopee收货方式有哪些

Shopee 是一家电子商务平台&#xff0c;提供多种不同的收货方式&#xff0c;具体的选项可能会根据您所在的地理位置和商品的类型而有所不同。以下是一些常见的 Shopee 收货方式&#xff1a; 1、快递配送&#xff1a;这是最常见的收货方式&#xff0c;您可以选择让商家使用物流…

开关时的瞬态高电压突变冲击--输入滤波电容可能引起的问题

在开关控制电路中&#xff0c;会出现开关瞬间产生一个高的电压冲击&#xff0c;可能会导致外设的保护机制&#xff0c;甚至损坏。 很多用电装置都由适配器通过一段比较长的电源线供电,在用电装置一端有电源滤波电容。随着产品向小型化,便携化方向发展&#xff0c;陶瓷电容在电源…

服务器安装Pytorch深度学习环境

最近要开始准备毕设啦&#xff0c;决定写一篇关于如何在实验室服务器安装Pytorch深度学习环境的博客&#xff0c;因为我使用的基本是Pytorch所以如果是使用Tensorflow的小伙伴就可以滑走啦~ 服务器统一安装过程 创建文件夹&#xff1a; mkdir miniconda(文件夹名) 转入新建文…

民乐社区关工委举办敬老爱老关爱活动

2023年10月27日&#xff0c;由华润银行支持&#xff0c;民乐社区关工委组织开展的敬老爱老关爱活动走进高乐亦嘉-光明社会福利院和中国文化名人大营救纪念馆&#xff0c;民乐社区关工委主任孙旗开&#xff0c;副主任常满彦、郭娜英、刘昕带领27名中老年人参与了本次活动。 参观…

国家数据局正式揭牌,隐私计算助力数据要素流通共享

2023年10月25日&#xff0c;国家数据局在京正式揭牌。根据中共中央、国务院印发的《党和国家机构改革方案》&#xff0c;国家数据局负责协调推进数据基础制度建设&#xff0c;统筹数据资源整合共享和开发利用&#xff0c;统筹推进数字中国、数字经济、数字社会规划和建设等。 多…

运维监控系统PIGOSS BSM 基础版重磅发布,永久免费

中小企业运维现状 当前多数中小型企业IT运维现状基本分为两部分&#xff1a; 1. 依靠传统的人工运维方式&#xff0c;无有效的监控工具辅助&#xff0c;导致故障发现不及时&#xff0c; 无法实时掌握IT运行状态。 2. 使用开源工具&#xff1a;开源工具因没有专业的售后技术…

如何在 Mac 上切换用户?

如果您想与其他人共享您的 Mac&#xff0c;创建一个独立于您的个人帐户的新用户帐户可能会有所帮助。然而&#xff0c;不利的一面是&#xff0c;时不时地在不同的用户帐户之间切换可能是一件耗时的事情。幸运的是&#xff0c;我创建了本指南&#xff0c;解释如何在 Mac 上快速切…

Android NDK开发详解之将 NDK 与其他构建系统配合使用

Android NDK开发详解之将 NDK 与其他构建系统配合使用 概览Autoconf非 Autoconf make 项目 注意&#xff1a;本页介绍的内容适用于 NDK r19 及更高版本。如果您使用的是旧版 NDK&#xff0c;请考虑进行升级。如果无法升级&#xff0c;请参阅独立工具链指南。 NDK 提供对 ndk-bu…

在安装和配置DVWA渗透测试环境遇到的报错问题

安装环境 前面的安装我参考的这个博主&#xff1a;渗透测试漏洞平台DVWA环境安装搭建及初级SQL注入-CSDN博客 修改bug 1.首先十分感谢提供帮助的博主&#xff0c;搭建DVWA Web渗透测试靶场_dvwa 白屏-CSDN博客&#xff0c;解决了我大多数问题&#xff0c;报错如下&#xff1…

[毕设记录]@开题调研:CAAI资源

发现这里面有些东西还是不错的 https://www.caai.cn/index.php?s/home/article/index/id/53.html其中我主要需要用到大模型技术白皮书

Wi-Fi 6和5G 在应用场景上的区别

在工作领域&#xff0c;我们经常会面临两个选择&#xff0c;场景的解决方案是要用5G还是WiFi 6&#xff0c;其实判断并不困难&#xff0c;但我们仍然还是从理论概念上区分一下。 文章目录 什么是Wi-Fi 6什么是5GWi-Fi 6和5G 的区别区别一&#xff1a;覆盖范围区别二&#xff1…

【Azure】存储服务:Azure 的存储账户

文章目录 一、前提知识&#xff08;建议了解&#xff09;二、介绍 Azure 存储帐户三、使用 Microsoft Azure 门户创建存储帐户 一、前提知识&#xff08;建议了解&#xff09; 在每一个云厂商中&#xff0c;都有自身的云存储&#xff0c;也有根据不同功能进行区分的不同类型的…

IP代理被低估的作用,你知道吗?

IP说简单不简单&#xff0c;说复杂也不复杂&#xff0c;打个比方&#xff0c;IP就好比我们上网的一个门牌号&#xff0c;每家每户都会有一个门牌号&#xff0c;而且是唯一的地址。而代理IP&#xff08;代理服务器&#xff09;是一个位于中间的服务器&#xff0c;充当客户端和目…

springboot2.x通用异常捕获

文章目录 demo地址实现效果引入基础类准备1.通用枚举与错误状态枚举2.定义通用返回结果3.自定义业务异常 统一异常捕获测试 demo地址 demo工程地址 实现效果 当我们输入1时&#xff0c;正常的返回通用的响应结果当我们输入2时&#xff0c;抛出异常&#xff0c;被捕获然后返回…

解决由于找不到mfc140u.dll无法继续执行此代码问题的4个方法

mfc140u.dll是Microsoft Foundation Class&#xff08;微软基础类库&#xff09;中的一个动态链接库文件&#xff0c;它包含了许多用于实现Windows应用程序的基本功能。当我们在编写或运行基于MFC的程序时&#xff0c;如果系统中缺少这个文件&#xff0c;就会出现“找不到mfc14…

电脑端微信多开方式

方法一&#xff1a;电脑微信分身法 大家只需要先按住键盘上的enter键不放&#xff0c;然后用鼠标点击电脑上的微信即可&#xff0c;这里的微信分身个数不限&#xff0c;大家根据自己的实际需要进行点击即可&#xff0c;点击了几次就可以开出几个微信。 注意&#xff1a;前提是…

vscode debug skills

1) VSCode 调试 C/C 代码时&#xff0c;如何显示动态分配的指针数组。 创建一个动态分配的一维数组: int n 10; int *array (int *)malloc(n*sizeof(int)); memset(array, 1, n*sizeof(int)); 如果直接 Debug 时查看 array 指针&#xff0c;并不能看到数组所有的值。 查看…

uniapp 提供了一种运行于视图层的专属js,微信叫做wxs

小程序里有几个谜一样的存在&#xff0c;微信的WXS、支付宝的SJS、百度的Filter。 很多开发者都不明白为什么要造这种语言脚本的轮子出来&#xff0c;甚至很多开发者根本不知道它们的存在。 其实几大小程序平台创造它们&#xff0c;都是为了解决性能问题&#xff0c;但不得不…