当前位置: 首页 > article >正文

【LeetCode刷题日记】112.递归中的「减法思维」:一题带你打通二叉树路径求和的任督二脉

个人主页北极的代码欢迎来访作者简介java后端学习者❄️个人专栏苍穹外卖日记SSM框架深入JavaWeb✨命运的结局尽可永在不屈的挑战却不可须臾或缺前言大家好我是代码不加冰来到了我们每日的刷题环节由于接近期末周每天自己学习的时间就变得少了但还是要坚持每天学一点到了暑假再猛学两个月想想还有点期待。摘要二叉树路径求和问题是一道经典的递归入门题看似简单却暗含递归思维的底层逻辑。本文以 LeetCode 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解释由于树是空的所以不存在根节点到叶子节点的路径。题目解析我们刚拿到这个题目可以联想到我们之前做过的一道题二叉树的所有路径在那里我们初步认识了回溯并具体实现得到了二叉树的所有路径而我们这题仅仅是要找到某一条或者几条的路径把这条路径的总和加起来看看是否等于我们的目标值路径是从根节点到叶子节点所谓的叶子节点就是没有左右子节点的节点。还有关键的一步就是我们怎么拿到一整条路径上的所有节点的和呢我们传入的是我们的目标值我们在递归的时候每一次递归都能得到当前的节点值那我们就可以拿目标值减去节点值如果最后目标值变成了0那么这条路径就是符合的。ps当然累加也是可以的但是需要额外维护一个状态也就是当前路径的节点值的和。具体的代码实现最直观的方法是深度优先搜索DFS从根节点向下递归遍历每经过一个节点就减去其值到达叶子节点时判断剩余和是否为 0。递归终止条件当前节点为空 → 返回false当前节点是叶子节点无左右孩子→ 返回节点值 targetSum否则递归检查左右子树目标值减去当前节点值java if (root.left null root.right null) { return root.val targetSum; // 叶子节点判断当前值是否等于剩余目标值 }这行代码的意思是如果当前节点是叶子节点判断root.val是否等于targetSum如果相等返回true如果不相等返回false逻辑运算符||的含义java return hasPathSum(root.left, targetSum - root.val) || hasPathSum(root.right, targetSum - root.val);这个||是逻辑或运算符特点短路特性如果左边返回true右边就不会执行只要有一条路径成功整个表达式就为true等价于java // 写法1用 || 简洁版 return dfs(left, newTarget) || dfs(right, newTarget); // 写法2展开后的等价代码 boolean leftResult hasPathSum(root.left, targetSum - root.val); if (leftResult) return true; // 左边找到了就不用查右边 boolean rightResult hasPathSum(root.right, targetSum - root.val); return rightResult;直观理解这句话可以翻译成当前节点到叶子节点的路径和是否能等于targetSum等于问①左子树中能否找到一条路径其和等于targetSum - 当前节点值②右子树中能否找到一条路径其和等于targetSum - 当前节点值只要①或②有一个成立答案就是true递归找到答案后不会瞬间传送回起点而是沿着调用链原路返回每层都执行一次return就像爬梯子一样一级一级退出来。这就是为什么虽然结果在很深的节点就确定了但程序还要执行那么多return的原因——它在清理调用栈把控制权逐级交还给上层。代码实现java class Solution { public boolean hasPathSum(TreeNode root, int targetSum) { // 节点为空没有路径 if (root null) { return false; } // 到达叶子节点判断当前值是否等于剩余目标值 if (root.left null root.right null) { return root.val targetSum; } // 递归左右子树目标值减去当前节点值 return hasPathSum(root.left, targetSum - root.val) || hasPathSum(root.right, targetSum - root.val); } }我们这里也可以使用迭代法用栈来实现。具体逻辑其实还是一样的不过我们可以用一个栈或者两个栈来实现我们入栈的顺序也要考虑好要右孩子先入栈栈是后进先出我们要先处理左孩子。方法一同时存储节点和当前和最直观java class Solution { public boolean hasPathSum(TreeNode root, int targetSum) { if (root null) { return false; } // 栈中存储节点, 从根到该节点的路径和 StackPairTreeNode, Integer stack new Stack(); stack.push(new Pair(root, root.val)); while (!stack.isEmpty()) { PairTreeNode, Integer pair stack.pop(); TreeNode node pair.getKey(); int currentSum pair.getValue(); // 到达叶子节点检查路径和是否等于目标值 if (node.left null node.right null) { if (currentSum targetSum) { return true; } } // 右孩子先入栈因为栈是后进先出左孩子会先处理 if (node.right ! null) { stack.push(new Pair(node.right, currentSum node.right.val)); } if (node.left ! null) { stack.push(new Pair(node.left, currentSum node.left.val)); } } return false; } }方法二使用两个栈更清晰java class Solution { public boolean hasPathSum(TreeNode root, int targetSum) { if (root null) { return false; } // 节点栈和对应的路径和栈 StackTreeNode nodeStack new Stack(); StackInteger sumStack new Stack(); nodeStack.push(root); sumStack.push(root.val); while (!nodeStack.isEmpty()) { TreeNode node nodeStack.pop(); int currentSum sumStack.pop(); // 检查叶子节点 if (node.left null node.right null) { if (currentSum targetSum) { return true; } } // 右孩子先入栈 if (node.right ! null) { nodeStack.push(node.right); sumStack.push(currentSum node.right.val); } if (node.left ! null) { nodeStack.push(node.left); sumStack.push(currentSum node.left.val); } } return false; } }结语如果对你有帮助请点赞关注收藏你的支持就是我最大的鼓励

相关文章:

【LeetCode刷题日记】112.递归中的「减法思维」:一题带你打通二叉树路径求和的任督二脉

🔥个人主页:北极的代码(欢迎来访) 🎬作者简介:java后端学习者 ❄️个人专栏:苍穹外卖日记,SSM框架深入,JavaWeb ✨命运的结局尽可永在,不屈的挑战却不可须臾或…...

精通yum/dnf:从依赖地狱到高效Linux软件包管理

1. 从“依赖地狱”到“一键管理”:为什么你需要精通yum/dnf在Linux世界里,尤其是Red Hat系(RHEL、CentOS、Fedora、Rocky Linux、AlmaLinux)的用户,软件包管理是绕不开的日常。如果你还在用rpm -ivh一个接一个地手动安…...

Google Earth Engine(GEE)——run with profiler查看我们所运行程序的描述、计算指标、内存、峰值内存和数量

分析器显示有关特定算法和计算的其他部分消耗的资源(CPU 时间、内存)的信息。这有助于诊断脚本运行缓慢或由于内存限制而失败的原因。要使用探查器,请单击“运行”按钮下拉菜单中的“使用探查器运行”选项。作为快捷方式,按住 Alt(或 Mac 上的 Option)并单击运行,或按 C…...

C语言状态模式实战:从设计思想到嵌入式状态机实现

1. 项目概述:从“状态”到“模式”的思维跃迁在嵌入式开发、游戏逻辑、网络协议解析乃至日常的业务流程控制中,我们常常会面对一个核心挑战:如何优雅地管理一个对象随着内部条件改变而表现出的不同行为?比如,一个自动售…...

如何在卡片悬停时添加内边距而不引起布局偏移

本文详解如何通过 box-sizing: border-box、合理设置宽高约束及子元素尺寸策略,在卡片 hover 时安全添加 padding,避免因盒模型计算导致的布局抖动或相邻卡片位移。 本文详解如何通过 box-sizing: border-box、合理设置宽高约束及子元素尺寸策略&am…...

宝塔面板如何定期清理日志垃圾_设置计划任务自动清理

...

终极AMD Ryzen处理器调试指南:如何用SMUDebugTool解锁隐藏性能潜力

终极AMD Ryzen处理器调试指南:如何用SMUDebugTool解锁隐藏性能潜力 【免费下载链接】SMUDebugTool A dedicated tool to help write/read various parameters of Ryzen-based systems, such as manual overclock, SMU, PCI, CPUID, MSR and Power Table. 项目地址…...

宝塔面板如何定期清理日志垃圾_设置计划任务自动清理.txt

...

AI智能体开发实战:agent-skills工具库核心技能解析与应用

1. 项目概述与核心价值最近在折腾AI智能体开发,发现一个挺有意思的现象:很多开发者,包括我自己在内,一开始都热衷于去研究那些大型的、功能全面的智能体框架,试图打造一个“全能”的AI助手。但实际落地时,往…...

重建二叉树-C++

分享一个大牛的人工智能教程。零基础!通俗易懂!风趣幽默!希望你也加入到人工智能的队伍中来!请轻击人工智能教程https://www.captainai.net/troubleshooter // 面试题7:重建二叉树 // 题目:输入某二叉树的前…...

煤矿智能化通信网络构建:从极端环境挑战到一体化方案实践

1. 项目概述:一次工业通信技术在传统能源领域的深度赋能实践最近刚结束的北京煤炭展,我们迈威通信的展台算是小火了一把。不少行业内的老朋友和新客户过来,聊得最多的不是我们的交换机、网关又出了什么新型号,而是“你们这套东西&…...

LSPatch:无需Root的Android应用模块化终极指南

LSPatch:无需Root的Android应用模块化终极指南 【免费下载链接】LSPatch LSPatch: A non-root Xposed framework extending from LSPosed 项目地址: https://gitcode.com/gh_mirrors/ls/LSPatch 你是否曾经羡慕iOS的越狱插件,却因Android设备未ro…...

AI智能体技能开发实战:从awesome-agent-skills到高效智能体构建

1. 项目概述:从技能清单到智能体构建的实战指南最近在折腾AI智能体(Agent)开发的朋友,估计都绕不开一个名字:awesome-agent-skills。这个由VoltAgent维护的开源项目,乍一看就是个GitHub上常见的“Awesome”…...

DeaDBeeF音频处理核心:DSP、重采样与均衡器技术详解

DeaDBeeF音频处理核心:DSP、重采样与均衡器技术详解 【免费下载链接】deadbeef DeaDBeeF Player 项目地址: https://gitcode.com/gh_mirrors/de/deadbeef DeaDBeeF Player是一款功能强大的开源音乐播放器,其卓越的音频处理能力离不开三大核心技术…...

Verilog数值转换:数字设计工程师必须掌握的底层规则与工程实践

1. 项目概述:为什么Verilog数值转换是数字设计的基石在数字电路设计和FPGA开发中,Verilog是我们描述硬件行为的主要语言。很多刚入行的朋友,包括我当年,都曾以为写Verilog就是写“另一种编程语言”,把C语言或Python的习…...

【NotebookLM+IEA/IRENA数据融合实战】:72小时内完成新型储能技术竞争力评估

更多请点击: https://codechina.net 第一章:NotebookLM能源技术研究 NotebookLM 是 Google 推出的基于 AI 的研究协作者工具,其核心能力在于对用户上传的文档进行语义理解与上下文驱动的问答。在能源技术研究领域,NotebookLM 可显…...

别再只用moviepy了!用Python的av库给视频批量加字幕,5分钟搞定

别再只用moviepy了!用Python的av库给视频批量加字幕,5分钟搞定 视频字幕添加是内容创作者的高频需求,无论是自媒体博主制作教程视频,还是教育工作者录制课程,精准的字幕不仅能提升观看体验,还能显著提高内容…...

AI工程师实战技能树:从特征工程到MLOps的完整指南

1. 项目概述与核心价值最近在GitHub上看到一个挺有意思的仓库,叫tqviet1978/ai-skills。光看名字,你可能会觉得这又是一个关于AI技能学习的普通教程合集。但当我点进去仔细研究后,发现它的定位和内容组织方式,与市面上大多数“AI学…...

图形引擎的跨平台之舞:Skia与Direct2D的深度对话

图形引擎的跨平台之舞:Skia与Direct2D的深度对话 【免费下载链接】skia Skia is a complete 2D graphic library for drawing Text, Geometries, and Images. See documentation for contribution instructions. 项目地址: https://gitcode.com/gh_mirrors/ski/sk…...

告别繁琐组态:用SVG + JavaScript 5分钟为你的工业设备创建可交互HMI组件

工业设备HMI组件开发革命:5分钟用SVGJavaScript打造智能交互界面 在工业自动化领域,人机界面(HMI)是连接设备与操作者的关键纽带。传统HMI开发往往陷入两个极端:要么使用笨重的组态软件进行繁琐配置,要么投入大量时间开发定制化界…...

如何用opendbc解决汽车CAN总线解码难题:一份完整的实践指南

如何用opendbc解决汽车CAN总线解码难题:一份完整的实践指南 【免费下载链接】opendbc a Python API for your car 项目地址: https://gitcode.com/gh_mirrors/op/opendbc 面对现代汽车复杂的电子控制系统,你是否曾经困惑于如何理解车辆内部的数据…...

浏览器串口调试革命:无需安装驱动,3分钟上手专业级串口助手

浏览器串口调试革命:无需安装驱动,3分钟上手专业级串口助手 【免费下载链接】SerialAssistant A serial port assistant that can be used directly in the browser. 项目地址: https://gitcode.com/gh_mirrors/se/SerialAssistant 还在为串口调试…...

Arm Neoverse V2内存架构与PCIe地址管理解析

1. Arm Neoverse V2内存架构设计精要 在Arm Neoverse V2的体系结构中,内存映射机制是其高性能计算能力的基石。这套架构通过精细的地址空间划分,实现了对各类硬件资源的高效管理。我们先来看一个典型的多芯片系统内存布局示例: Chip 0: 0x0…...

Cairo高级特性解析:泛型、Trait系统和元编程的深度应用

Cairo高级特性解析:泛型、Trait系统和元编程的深度应用 【免费下载链接】cairo Cairo is the first Turing-complete language for creating provable programs for general computation. 项目地址: https://gitcode.com/gh_mirrors/ca/cairo Cairo作为首个支…...

InstructPix2Pix:5分钟掌握AI图像编辑的终极指南

InstructPix2Pix:5分钟掌握AI图像编辑的终极指南 【免费下载链接】instruct-pix2pix 项目地址: https://gitcode.com/gh_mirrors/in/instruct-pix2pix 你是否曾经幻想过,只需一句话就能让图片中的对象变成你想要的样子?比如把普通的大…...

《从GIS前端到AIGC大厂:WebGIS、WebGL、Three.js技术栈的底层能力拆解与岗位适配指南》

前端GIS技术栈:从图形学底层到AIGC营销增长的全链路实战指南 (附大厂AI前端JD精准匹配与可落地项目) 🔖 目录理论篇:GIS中必学的图形学、WebGL、Three.js核心内容(含GIS实战细节) 1.1 计算机图形…...

终极指南:在Windows上安装安卓应用的简单解决方案

终极指南:在Windows上安装安卓应用的简单解决方案 【免费下载链接】APK-Installer An Android Application Installer for Windows 项目地址: https://gitcode.com/GitHub_Trending/ap/APK-Installer 你是否曾经希望在Windows电脑上直接运行手机应用&#xf…...

智能识别整理会议内容,让开会后怎么列待办更清晰更省事

作为经常跑客户、开会议的销售,此前我常被整理沟通内容、梳理待办的工作困扰,不仅耗时久,还容易漏记客户需求、搞错时间节点。结合大半年的实测体验,整理出一套AI整理方法,能快速清晰梳理待办,节省大量时间…...

如何免费解锁雀魂全角色皮肤:终极完整配置指南

如何免费解锁雀魂全角色皮肤:终极完整配置指南 【免费下载链接】majsoul_mod_plus 雀魂解锁全角色、皮肤、装扮等,支持全部服务器。 项目地址: https://gitcode.com/gh_mirrors/ma/majsoul_mod_plus 还在为无法获得心仪的雀魂角色而烦恼吗&#x…...

开发上下文管理工具:原理、实现与工程实践

1. 项目概述:一个为开发者量身定制的上下文管理工具如果你和我一样,每天要在多个项目、多种技术栈、甚至多个开发环境之间反复横跳,那你一定对“上下文切换”这个词深恶痛绝。我说的不是操作系统的上下文切换,而是我们开发者大脑里…...