力扣每日一题day36[112.路径总和]

给你二叉树的根节点 root 和一个表示目标和的整数 targetSum 。判断该树中是否存在 根节点到叶子节点 的路径,这条路径上所有节点值相加等于目标和 targetSum 。如果存在,返回 true ;否则,返回 false 。

叶子节点 是指没有子节点的节点。

示例 1:

输入:root = [5,4,8,11,null,13,4,7,2,null,null,null,1], targetSum = 22
输出:true
解释:等于目标和的根节点到叶节点路径如上图所示。

示例 2:

输入:root = [1,2,3], targetSum = 5
输出:false
解释:树中存在两条根节点到叶子节点的路径:
(1 --> 2): 和为 3
(1 --> 3): 和为 4
不存在 sum = 5 的根节点到叶子节点的路径。

示例 3:

输入:root = [], targetSum = 0
输出:false
解释:由于树是空的,所以不存在根节点到叶子节点的路径。

递归

可以使用深度优先遍历的方式来遍历二叉树

确定递归函数的参数和返回类型

参数:需要二叉树的根节点,还需要一个计数器,这个计数器用来计算二叉树的一条边之和是否正好是目标和,计数器为int型。

再来看返回值,递归函数什么时候需要返回值?什么时候不需要返回值?这里总结如下三点:

  • 如果需要搜索整棵二叉树且不用处理递归返回值,递归函数就不要返回值。

  • 如果需要搜索整棵二叉树且需要处理递归返回值,递归函数就需要返回值。

  • 如果要搜索其中一条符合条件的路径,那么递归一定需要返回值,因为遇到符合条件的路径了就要及时返回。

而本题我们要找一条符合条件的路径,所以递归函数需要返回值,及时返回,那么返回类型是什么呢?

遍历的路线,并不要遍历整棵树,所以递归函数需要返回值,可以用bool类型表示。

所以代码如下:

boolean traversal(TreeNode cur,int targetSum)

确定终止条件

不要去累加然后判断是否等于目标和,那么代码比较麻烦,可以用递减,让计数器count初始为目标和,然后每次减去遍历路径节点上的数值。

如果最后count == 0,同时到了叶子节点的话,说明找到了目标和。

如果遍历到了叶子节点,count不为0,就是没找到。

递归终止条件代码如下:

if(cur.left==null && cur.right==null && targetSum==0) return true;
if(cur.left==null && cur.right==null) return false;

确定单层递归的逻辑

因为终止条件是判断叶子节点,所以递归的过程中就不要让空节点进入递归了。

递归函数是有返回值的,如果递归函数返回true,说明找到了合适的路径,应该立刻返回。

代码如下:

if(cur.left!=null) { // 左 (空节点不遍历)// 遇到叶子节点返回true,则直接返回truetargetSum-=cur.left.val;if(traversal(cur.left,targetSum)) return true; // 注意这里有回溯的逻辑
}
if(cur.right!=null){ // 右 (空节点不遍历)// 遇到叶子节点返回true,则直接返回truetargetSum-=cur.right.val;if(traversal(cur.right,targetSum)) return true; // 注意这里有回溯的逻辑
}
return false;

以上代码中是包含着回溯的,没有回溯,如何后撤重新找另一条路径呢。

回溯隐藏在targetSum这里, 因为把targetSum-=cur.right.val; 直接作为参数传进去,函数结束,targetSum的数值没有改变。

为了把回溯的过程体现出来,可以改为如下代码:

if(cur.left!=null){targetSum-=cur.left.val;if(traversal(cur.left,targetSum)) return true;targetSum+=cur.left.val;
}
if(cur.right!=null){targetSum-=cur.right.val;if(traversal(cur.right,targetSum)) return true;targetSum+=cur.right.val;
}
return false;
/*** Definition for a binary tree node.* public class TreeNode {*     int val;*     TreeNode left;*     TreeNode right;*     TreeNode() {}*     TreeNode(int val) { this.val = val; }*     TreeNode(int val, TreeNode left, TreeNode right) {*         this.val = val;*         this.left = left;*         this.right = right;*     }* }*/
class Solution {public boolean hasPathSum(TreeNode root, int targetSum) {if(root==null) return false;return traversal(root,targetSum-root.val);}boolean traversal(TreeNode cur,int targetSum){if(cur.left==null && cur.right==null && targetSum==0) return true;if(cur.left==null && cur.right==null) return false;if(cur.left!=null){targetSum-=cur.left.val;if(traversal(cur.left,targetSum)) return true;targetSum+=cur.left.val;}if(cur.right!=null){targetSum-=cur.right.val;if(traversal(cur.right,targetSum)) return true;targetSum+=cur.right.val;}return false;}
}

迭代

如果使用栈模拟递归的话,那么如果做回溯呢?

此时栈里一个元素不仅要记录该节点指针,还要记录从头结点到该节点的路径数值总和。

class solution {public boolean haspathsum(treenode root, int targetsum) {if(root == null) return false;stack<treenode> stack1 = new stack<>();stack<integer> stack2 = new stack<>();stack1.push(root);stack2.push(root.val);while(!stack1.isempty()) {int size = stack1.size();
​for(int i = 0; i < size; i++) {treenode node = stack1.pop();int sum = stack2.pop();
​// 如果该节点是叶子节点了,同时该节点的路径数值等于sum,那么就返回trueif(node.left == null && node.right == null && sum == targetsum) {return true;}// 右节点,压进去一个节点的时候,将该节点的路径数值也记录下来if(node.right != null){stack1.push(node.right);stack2.push(sum + node.right.val);}// 左节点,压进去一个节点的时候,将该节点的路径数值也记录下来if(node.left != null) {stack1.push(node.left);stack2.push(sum + node.left.val);}}}return false;}
}

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

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

相关文章

SQL基础:查询的基本使用

上一节我们讲述了记录的基本操作&#xff0c;这一节我们来单独讲一下查询。 查询基本结构 首先我们来看下查询的基本结构 SELECTcolumn1,column2,... FROMtable_name [WHEREcondition] [GROUP BYcolumn1, column2, ...] [HAVINGaggregate_function(column) condition] [ORDE…

【算法】算法题-20231222

这里写目录标题 一、1002. 查找共用字符二、1047. 删除字符串中的所有相邻重复项三、面试题 01.04. 回文排列 一、1002. 查找共用字符 给你一个字符串数组 words &#xff0c;请你找出所有在 words 的每个字符串中都出现的共用字符&#xff08; 包括重复字符&#xff09;&…

Linux cat命令教程:如何连接文件并打印到标准输出设备上(附实例详解和注意事项)

Linux cat命令介绍 cat命令&#xff0c;全称为concatenate&#xff0c;用于连接文件并打印到标准输出设备上。 Linux cat命令适用的Linux版本 cat命令在所有Linux发行版中都是可用的&#xff0c;包括但不限于Ubuntu, Debian, Fedora, RHEL, CentOS等。 Linux cat命令的基本…

SpringIOC之MethodBasedEvaluationContext

博主介绍&#xff1a;✌全网粉丝5W&#xff0c;全栈开发工程师&#xff0c;从事多年软件开发&#xff0c;在大厂呆过。持有软件中级、六级等证书。可提供微服务项目搭建与毕业项目实战&#xff0c;博主也曾写过优秀论文&#xff0c;查重率极低&#xff0c;在这方面有丰富的经验…

bootstrap基础

&#xff08;一&#xff09;bootstrap初识 bootstrap由美国数学家Efron于20世界70年代创建。 bootstrap方法用于样本数较少时的数学统计和参数估计。其数学原理基于格里汶科定理。 格里汶科&#xff08; G l i v e n k o &#xff09;定理&#xff1a; \color{red}格里汶科&a…

React和umi搭建项目的操作步骤

​​​​​​一、react脚手架新建项目 (1.1)、命令行 前提&#xff1a;react ES2015,nodejs v8 npx create-react-app myReactName //2022年v16以下版本 myReactName(自定义项目名) react中文官网&#xff0c;快速上手&#xff1a;react中文官网 react框架&#xff0c;…

基于Linphone android sdk开发Android软话机

1.Linphone简介 1.1 简介 LinPhone是一个遵循GPL协议的开源网络电话或者IP语音电话&#xff08;VOIP&#xff09;系统&#xff0c;其主要如下。使用linphone&#xff0c;开发者可以在互联网上随意的通信&#xff0c;包括语音、视频、即时文本消息。linphone使用SIP协议&#…

CGAL的3D Alpha Shapes

假设我们给定一个二维或三维的点集S&#xff0c;我们希望得到类似“这些点形成的形状”的东西。这是一个相当模糊的概念&#xff0c;可能有许多可能的解释&#xff0c;阿尔法形状就是其中之一。阿尔法形状可用于从密集的无组织数据点集进行形状重建。事实上&#xff0c;阿尔法形…

Go和Java实现命令模式

Go和Java实现命令模式 下面通过一个烧烤的例子来说明命令模式的使用。 1、命令模式 命令模式是一种数据驱动的设计模式&#xff0c;它属于行为型模式。请求以命令的形式包裹在对象中&#xff0c;并传给调用对象。调 用对象寻找可以处理该命令的合适的对象&#xff0c;并把该…

在 MyBatis 中<应该怎么写

在 MyBatis 中&#xff0c;< 符号在 XML 配置文件中是一个特殊字符&#xff0c;用于标记 XML 标签的开始。因此&#xff0c;如果你在 MyBatis 的 if 标签中直接使用 < 符号&#xff0c;它会被解析为 XML 标签的开始&#xff0c;从而导致解析错误。 为了避免这个问题&…

用户管理第2节课--idea 2023.2 后端--实现基本数据库操作(操作user表) -- 自动生成

一、插件 Settings... 1.1 File -- Settings 1.2 Settings -- Plugins 1.2.1 搜索框&#xff0c;也可以直接搜索 1.3 Plugins -- 【输入 & 搜索】mybatis 1.3.1 插件不同功能介绍 1.3.2 翻译如下 1.4 选中 Update&#xff0c;更新下 1.4.1 更新中 1.4.2 Restart IDE 1…

C++ 类的析构函数和构造函数

构造函数 类的构造函数是类的一种特殊的成员函数&#xff0c;它会在每次创建类的新对象时执行。主要用来在创建对象时初始化对象即为对象成员变量赋初始值。 构造函数的名称与类的名称是完全相同的&#xff0c;并且不会返回任何类型&#xff0c;也不会返回 void。构造函数可用…

ARM GIC(一) cortex-A 处理器中断简介

对于ARM的处理器&#xff0c;中断给处理器提供了触觉&#xff0c;使处理器能够感知到外界的变化&#xff0c;从而实时的处理。本系列博文&#xff0c;是以ARM cortex-A系列处理器&#xff0c;来介绍ARM的soc中&#xff0c;中断的处理。 ARM cortex-A系列处理器&#xff0c;提供…

[node] Node.js的路由

[node] Node.js的路由 路由 & 路由解析路由信息的整合URL信息路由处理逻辑路由逻辑与URL信息的整合路由的使用 路由 & 路由解析 路由需要提供请求的 URL 和其他需要的 GET/POST 参数&#xff0c;随后路由需要根据这些数据来执行相应的代码。 因此&#xff0c;根据 HT…

Android 13 - Media框架(25)- OMXNodeInstance(二)

上一节我们了解了 OMXNodeInstance 的创建过程&#xff0c;以及 IOmx 服务和 OMXNodeInstance、OMX组件之间的联系。这一节我们将一起了解 ACodec 是如何通过 OMXNodeInstance 这个中间层进行端口定义设置&#xff0c;以及端口Buffer分配的。 OMXNodeInstance 的代码还是比较长…

Python之Django项目的功能配置

1.创建Django项目 进入项目管理目录&#xff0c;比如&#xff1a;D盘 执行命令&#xff1a;diango-admin startproject demo1 创建项目 如果提示diango命令不存在&#xff0c;搜索diango-admin程序的位置&#xff0c;然后加入到环境变量path中。 进入项目&#xff0c;cd demo…

CentOS 7 Tomcat服务的安装

前提 安装ava https://blog.csdn.net/qq_36940806/article/details/134945175?spm1001.2014.3001.5501 1. 下载 wget https://mirrors.tuna.tsinghua.edu.cn/apache/tomcat/tomcat-9/v9.0.84/bin/apache-tomcat-9.0.84.tar.gzps: 可选择自己需要的版本下载安装https://mirr…

【单调栈】LeetCode2334:元素值大于变化阈值的子数组

作者推荐 map|动态规划|单调栈|LeetCode975:奇偶跳 涉及知识点 单调栈 题目 给你一个整数数组 nums 和一个整数 threshold 。 找到长度为 k 的 nums 子数组&#xff0c;满足数组中 每个 元素都 大于 threshold / k 。 请你返回满足要求的 任意 子数组的 大小 。如果没有这…

记录Ubuntu20.04安装mujoco与安装mujoco_py并测试时提示Cython.Compiler.Errors.CompileError的解决方案

安装mujoco可以参考如下来链接&#xff1a; Ubuntu20.04安装mujoco&#xff1a; https://blog.csdn.net/qq_47997583/article/details/125400418 安装mujoco_py并测试时提示Cython.Compiler.Errors.CompileError&#xff1a; https://blog.csdn.net/m0_38122847/article/de…

Git 合并两个项目

前言 在 Git 中合并两个项目的代码需要一些步骤&#xff0c;尤其是如果这两个项目有不同的版本历史或者是独立的 Git 仓库。以下是一般的步骤&#xff1a; 克隆第一个项目&#xff1a; 在你的本地机器上克隆第一个项目的 Git 仓库。 git clone <URL_of_first_project>…