目录

1. 啥时候用二叉树?

(1)典型问题

(2)核心思路

2. BFS、DFS、BST

2.1 广度优先搜索BFS

(1)适用任务

(2)解决思路​​:使用队列逐层遍历

2.2 深度优先搜索DFS

(1)三种变体(前中后序)

(2)解决思路:递归实现

2.3 二叉搜索树BST

3. LeetCode

3.1 BFS

(1)199 二叉树的右视图

(2)1161 最大层内元素和

3.2 DFS

(1)104 二叉树的最大深度

(2)872 叶子相似的树

(3)1448 统计二叉树中好节点的数目

(4)1372 二叉树中的最长交错路径

(5)236 二叉树的最近公共祖先

3.3 BST

(1)700 二叉搜索树中的搜索

(2)450 删除二叉搜索树中的节点

(3)98 验证二叉搜索树

(4)230 二叉搜索树中第k小的元素


1. 啥时候用二叉树?

(1)典型问题

  • 分层数据处理(文件系统、组织架构)

  • 高效搜索(BST中查找/插入/删除)

  • 路径问题(根节点到叶节点的路径)

  • 树形结构操作(镜像、深度、平衡性判断)

  • 表达式解析(语法树)

(2)核心思路

def solve(root):if root is None:  # 关键:始终先处理空节点return base_value  # 如深度为0,路径为空列表等# 递归分解子问题left_result = solve(root.left)     # 处理左子树right_result = solve(root.right)   # 处理右子树# 合并结果(根据问题类型选择策略)return combine(root.val, left_result, right_result)

2. BFS、DFS、BST

2.1 广度优先搜索BFS

(1)适用任务

-- 层序遍历(按层级输出节点)

-- 最短路径(根节点到目标节点的最小深度)

-- 寻找最近邻节点

(2)解决思路​​:使用队列逐层遍历

from collections import dequedef bfs(root):if not root: return []queue = deque([root])result = []while queue:level = []for _ in range(len(queue)):  # 遍历当前层node = queue.popleft()level.append(node.val)if node.left: queue.append(node.left)if node.right: queue.append(node.right)result.append(level)  # 保存当前层结果return result

2.2 深度优先搜索DFS

(1)三种变体(前中后序)

遍历方式​

应用场景

​解决任务​

​操作顺序​

​前序遍历​

节点初始化、路径记录、自顶向下操作

复制树、表达式前缀表示

根 → 左 → 右

​中序遍历​

二叉搜索树操作、顺序相关处理

BST升序输出、表达式解析

左 → 根 → 右

​后序遍历​

子树信息统计、依赖子树结果的操作

子树统计、内存释放

左 → 右 → 根

关键判断依据:​​当前节点操作与子树操作的关系​

  1. 如果操作依赖子树结果 → 用后序遍历(如:树深度、子树统计)

  2. 如果操作在前子树操作前必须完成 → 用前序遍历(如:路径记录、节点初始化)

  3. 如果涉及顺序处理 → 用中序遍历(如:BST中序遍历有序)

(2)解决思路:递归实现

""" 前序遍历 """
def preorder(root):if not root: returnprint(root.val)          # 先操作根节点preorder(root.left)preorder(root.right)""" 中序遍历 (BST关键) """
def inorder(root):if not root: returninorder(root.left)print(root.val)          # 在中间操作节点inorder(root.right)""" 后序遍历 """
def postorder(root):if not root: returnpostorder(root.left)postorder(root.right)print(root.val)          # 最后操作根节点

2.3 二叉搜索树BST

左子树节点值 < 根节点值 < 右子树节点值

​(1)典型任务​

-- 查找元素(时间复杂度 ​​O(log n)​​)

-- 插入/删除节点(保持BST性质)

-- 范围查询(如找出值在 [low, high] 间的节点)

(2)代码模板

""" BST查找 """
def search(root, target):while root:if root.val == target: return Trueroot = root.left if target < root.val else root.rightreturn False""" BST插入(递归版)"""
def insert(root, val):if not root: return TreeNode(val)if val < root.val: root.left = insert(root.left, val)elif val > root.val: root.right = insert(root.right, val)return root  # 返回更新后的子树根节点""" 验证BST(中序遍历应用)"""
def isValidBST(root):stack, prev = [], float('-inf')while stack or root:while root:  # 深入左子树stack.append(root)root = root.leftroot = stack.pop()if root.val <= prev: return False  # 破坏升序prev = root.valroot = root.right  # 转向右子树return True

3. LeetCode

3.1 BFS

(1)199 二叉树的右视图

给定一个二叉树的 根节点 root,想象自己站在它的右侧,按照从顶部到底部的顺序,返回从右侧所能看到的节点值。

本质上就是二叉树每一层的最后一个入队的节点

from collections import deque
class Solution(object):def rightSideView(self, root):""":type root: Optional[TreeNode]:rtype: List[int]"""if not root: return []result=[]quene = deque([root])while quene:size=len(quene)for i in range(size):node = quene.popleft()if node.left: quene.append(node.left)if node.right:quene.append(node.right)cur_level_last = node.valresult.append(cur_level_last)return result

(2)1161 最大层内元素和

给你一个二叉树的根节点 root。设根节点位于二叉树的第 1 层,而根节点的子节点位于第 2 层,依此类推。请返回层内元素之和最大的那几层(可能只有一层)的层号,并返回其中最小的那个。

from collections import deque
class Solution(object):def maxLevelSum(self, root):""":type root: Optional[TreeNode]:rtype: int"""if not root: return 0quene = deque([root])level=1max_sum=[root.val, level]while quene:level_sum = 0level += 1for i in range(len(quene)):node = quene.popleft()level_sum += node.valif node.left: quene.append(node.left)if node.right:quene.append(node.right)if max_sum[0]<level_sum:max_sum = [level_sum, level-1]return max_sum[1]

3.2 DFS

(1)104 二叉树的最大深度

给定一个二叉树 root ,返回其最大深度。二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。

DFS方法:后序遍历,先看左右子树的深度,更深的+1即为整棵树的最大深度。

class Solution(object):def maxDepth(self, root):""":type root: Optional[TreeNode]:rtype: int"""if not root:return 0left_depth = self.maxDepth(root.left)right_depth = self.maxDepth(root.right)return max(left_depth,right_depth)+1

BFS方法:

from collections import deque
class Solution(object):def maxDepth(self, root):""":type root: Optional[TreeNode]:rtype: int"""if not root:return 0quene = deque([root])   ## 队列中存的是当前层的所有节点result = []             ## 用来保存每一层的节点while quene:cur_level = []              ## 当前层的节点level_size = len(quene)     ## 当前层有几个节点for i in range(level_size):node = quene.popleft()  cur_level.append(node.val)  ## 将当前节点加入当前层中if node.left:   quene.append(node.left)if node.right:  quene.append(node.right)result.append(cur_level)return len(result)   

(2)872 叶子相似的树

如果有两棵二叉树的叶值序列是相同,那么我们就认为它们是 叶相似 的。如果给定的两个根结点分别为 root1 和 root2 的树是叶相似的,则返回 true;否则返回 false 。

DFS遍历都是先左后右的,因此均能保证叶子节点的顺序。

from collections import deque
class Solution(object):def find_leaves(self,root,leaves):if not root:    return[]left_leaves = self.find_leaves(root.left,leaves)if not root.left and not root.right:leaves.append(root.val)right_leaves = self.find_leaves(root.right,leaves)return leavesdef leafSimilar(self, root1, root2):""":type root1: Optional[TreeNode]:type root2: Optional[TreeNode]:rtype: bool"""leaves1=[]leaves2=[]leaves1 = self.find_leaves(root1,leaves1)leaves2 = self.find_leaves(root2,leaves2)if leaves1==leaves2:return Trueelse:return False

(3)1448 统计二叉树中好节点的数目

给你一棵根为 root 的二叉树,请你返回二叉树中好节点的数目。「好节点」X 定义为:从根到该节点 X 所经过的节点中,没有任何节点的值大于 X 的值。

采用前序遍历(根 → 左 → 右)

根节点优先处理​​:在访问子节点前先判断当前节点,符合路径顺序

及时更新最大值​​:当遇到更大节点时,立即更新路径最大值传递给子节点

class Solution(object):def dfs(self,root,cur_max):if not root:    return 0count = 0if root.val>=cur_max:count=1cur_max = root.valcount += self.dfs(root.left,cur_max)count += self.dfs(root.right,cur_max)return countdef goodNodes(self, root):""":type root: Optional[TreeNode]:rtype: int"""cur_max=-10001return self.dfs(root,cur_max)

(4)1372 二叉树中的最长交错路径

给你一棵以 root 为根的二叉树,二叉树中的交错路径定义如下:

  • 选择二叉树中 任意 节点和一个方向(左或者右)。
  • 如果前进方向为右,那么移动到当前节点的的右子节点,否则移动到它的左子节点。
  • 改变前进方向:左变右或者右变左。
  • 重复第二步和第三步,直到你在树中无法继续移动。

交错路径的长度定义为:访问过的节点数目 - 1(单个节点的路径长度为 0 )。请你返回给定树中最长 交错路径 的长度。

使用后序遍历:①当前节点的状态计算​​依赖子节点状态​

②需要先知道子节点的 left_path 和 right_path 才能计算当前节点

class Solution(object):def longestZigZag(self, root):""":type root: Optional[TreeNode]:rtype: int"""    self.max_path = 0def dfs(node):"""后序遍历返回(left_path, right_path)""""""left_path: 从当前节点出发,第一步向左走能形成的最长交错路径长度""""""right_path: 从当前节点出发,第一步向右走能形成的最长交错路径长度"""if not node:return (0, 0)left_res = dfs(node.left)  right_res = dfs(node.right)"""从当前节点向左走一步到左子节点(+1)然后需要向右走,查询左子节点的​​向右走状态​​(right_path,即left_res[1])"""left_path = 1 + left_res[1] if node.left else 0  """从当前节点向右走一步到右子节点(+1)然后需要向左走,查询右子节点向左走的状态(left_path,即right_res[0])"""right_path = 1 + right_res[0] if node.right else 0self.max_path = max(self.max_path, left_path, right_path)return (left_path, right_path)dfs(root)return self.max_path

(5)236 二叉树的最近公共祖先

祖先可能的情况:

(1)p 和 q 分属不同子树 → 当前根节点是 LCA

(2)p 和 q 在同一子树 → LCA 在该子树中

(3)p 或 q 自身就是 LCA(祖孙关系)

→ 采用后序遍历顺序​​(左右根):

先深入子树寻找节点,再处理当前节点判断逻辑

class Solution(object):def lowestCommonAncestor(self, root, p, q):""":type root: TreeNode:type p: TreeNode:type q: TreeNode:rtype: TreeNode"""if not root or root==p or root==q:return rootleft = self.lowestCommonAncestor(root.left,p,q)     ## 在左子树中找到的p或q(或LCA)right = self.lowestCommonAncestor(root.right,p,q)   ## 在右子树中找到的p或q(或LCA)if left and right:  ## p和q分别在root的左右子树中 return root     ## root是它们最低层级的共同祖先if left:            ## 两个节点必定都在左子树中## 此时left要么是p和q中的一个(如果尚未找到两者关系),要么是p和q的LCA(如果已找到两者关系)return left     return right

3.3 BST

(1)700 二叉搜索树中的搜索

给定二叉搜索树(BST)的根节点 root 和一个整数值 val。你需要在 BST 中找到节点值等于 val 的节点。 返回以该节点为根的子树。 如果节点不存在,则返回 null 。

class Solution(object):def searchBST(self, root, val):""":type root: Optional[TreeNode]:type val: int:rtype: Optional[TreeNode]"""if not root: return nullwhile root:if root.val==val:return rootelif root.val<val:root=root.rightelse:root=root.left

(2)450 删除二叉搜索树中的节点

要被删除的节点存在三种情况:

1. 叶子节点​​:直接删除(返回None)

​2. 只有一个子节点​​:用子节点替代当前节点

实现:直接返回子节点是让父节点直接指向孙子节点

​3. 有两个子节点​​:找到前置节点(当前节点左子树中最右侧节点)替换

实现:用前置节点值覆盖当前节点值 → 删除前置节点(递归调用)

class Solution(object):def deleteNode(self, root, key):""":type root: Optional[TreeNode]:type key: int:rtype: Optional[TreeNode]"""if not root: return Noneif key>root.val:    ## key比当前节点大,在右子树中删root.right=self.deleteNode(root.right,key)elif key<root.val:  ## key比当前节点小,在左子树中删root.left=self.deleteNode(root.left,key)else:       ## 找到要删的节点了,有以下4种情况""" 1.当前节点是叶子节点 → 直接删除"""if not root.left and not root.right:return None""" 2.当前节点只有左孩子 → 直接用左孩子替代当前节点"""elif not root.right:return root.left""" 3.当前节点只有右孩子 → 直接用右孩子替代当前节点 """elif not root.left:return root.right""" 4. 当前节点左右孩子都有 → 用左子树的最右侧节点替代 """else:## 寻找前置节点pre = root.left     while pre.right:pre=pre.right## 前置节点值赋给当前节点root.val = pre.val ## 删除原前置节点 root.left = self.deleteNode(root.left,pre.val)return root

(3)98 验证二叉搜索树

方案一:递归实现

每个节点都有值范围约束:(low,high)

左子树继承上界:(low,node.val),右子树继承下界:(node.val,high)

class Solution(object):def isValidBST(self, root):""":type root: Optional[TreeNode]:rtype: bool"""def validate(node, low=float('-inf'), high=float('inf')):if not node:return Trueif node.val<=low or node.val>=high:return Falseis_left = validate(node.left, low, node.val)is_right = validate(node.right, node.val, high)return is_left and is_rightreturn validate(root)

方案二:中序遍历验证

使用模拟中序遍历过程,比较当前节点与前一个节点的值

class Solution(object):def isValidBST(self, root):stack=[]pre=Nonewhile stack or root:""" 左 """while root:     stack.append(root)root=root.left""" 根 """root=stack.pop()if pre is not None and root.val<=pre:   return False    ## 当前值比pre值(其左侧)小""" 右 """pre=root.valroot=root.rightreturn True

(4)230 二叉搜索树中第k小的元素

因为搜索树的中序遍历得到一个递增序列,所以本质上就是求中序遍历的第k个值。

class Solution(object):def kthSmallest(self, root, k):""":type root: Optional[TreeNode]:type k: int:rtype: int"""stack=[]count=0while root or stack:## 左while root:stack.append(root)root=root.left## 根root=stack.pop()count+=1if count==k:   ## 是否是第k个 return root.val## 右root=root.right

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

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

相关文章

<c1:C1DateTimePicker的日期时间控件,控制日期可以修改,时间不能修改,另外控制开始时间的最大值比结束时间小一天

两个时间控件 <c1:C1DateTimePicker Width"170" EditMode"DateTime" CustomDateFormat"yyyy-MM-dd" CustomTimeFormat"HH:mm:ss" Style"{StaticResource ListSearch-DateTimePicker}" x:Name"dateTimePicker"…

文件完整性监控工具:架构和实现

文件完整性监控(FIM)作为一道关键的防御层&#xff0c;确保系统和网络中文件及文件夹的完整性与安全性。文件完整性监控工具通过监控关键文件的变更并检测未经授权的修改&#xff0c;提供关于潜在安全漏洞、恶意软件感染和内部威胁的早期警报。为了使文件完整性监控工具发挥实效…

Linux信号量和信号

1.温故知新上一篇博客&#xff0c;我们又知道了一种进程间通信的方案&#xff1a;共享内存。它是在物理内存中用系统调用给我们在物理内存开辟一个共享内存&#xff0c;可以由多个进程的页表进行映射&#xff0c;共享内存不和管道一样&#xff0c;它的生命周期是随内核的&#…

腾讯测试岗位面试真题分析

以下是对腾讯测试工程师面试问题的分类整理、领域占比分析及高频问题精选&#xff08;基于​​92道问题&#xff0c;总出现次数118次​​&#xff09;。问题按​​7大技术领域​​划分&#xff0c;高频问题标注优先级&#xff08;1-5&#x1f31f;&#xff09;&#xff1a; 不…

全面解析远程桌面:功能实现、性能优化与安全防护全攻略

远程桌面技术已成为工作与生活中不可或缺的协作工具&#xff0c;但在实际应用中&#xff0c;用户常遇到连接失败、卡顿延迟、安全隐患等问题。本文从远程桌面功能原理、网络与性能优化、安全防护策略、跨平台兼容性等角度&#xff0c;详细解析常见问题的解决方案&#xff0c;并…

【问题】Mybatis-plus框架使用@Select注解编写查询SQL,json字段查询转换失败

问题描述在使用mybaits-plus的时候定义的Mapper接口实现了BaseMapper&#xff0c;没有编写Mapper对应的xml&#xff0c;大部分查询使用框架的接口进行查询基本属性返回都是正常&#xff0c;复杂对象在sql中会进行查询&#xff0c;但是返回对象中却未包含相关属性。问题原因 没有…

Python多线程实现大文件下载

Python多线程实现大文件下载 在互联网时代&#xff0c;文件下载是日常操作之一&#xff0c;尤其是大文件&#xff0c;如软件安装包、高清视频等。然而&#xff0c;网络条件不稳定或带宽有限时&#xff0c;下载速度会变得很慢&#xff0c;令人抓狂。幸运的是&#xff0c;通过多线…

【R语言】RStudio 中的 Source on Save、Run、Source 辨析

RStudio 中的 Source on Save、Run、Source 辨析 在使用 RStudio 进行 R 语言开发时&#xff0c;我们会在主界面左上角看见三个按钮&#xff1a;Source on Save、Run、Source 。 本文将带你从概念、使用方法、快捷键、使用场景以及注意事项等方面详细解析这三个功能。 文章目录…

蓝桥杯算法之搜索章 - 4

目录 文章目录 前言 一、记忆化搜索 二、题目概略 三、斐波拉契数 四、Function 五、天下第一 六、滑雪 总结 亲爱的读者朋友们&#xff0c;大家好啊&#xff01;不同的时间&#xff0c;相同的地点&#xff0c;今天又带来了关于搜索部分的讲解。接下来我将接着我前面文章的内容…

抗量子加密技术前瞻:后量子时代的密码学革命

目录抗量子加密技术前瞻&#xff1a;后量子时代的密码学革命1. 量子计算威胁现状1.1 量子霸权里程碑1.2 受威胁算法1.3 时间紧迫性2. 抗量子密码学体系2.1 技术路线对比2.2 数学基础革新3. 标准化进程3.1 NIST PQC标准化时间线3.2 当前推荐算法4. 技术实现方案4.1 Kyber密钥交换…

基于STM32设计的矿山环境监测系统(NBIOT)_262

文章目录 一、前言 1.1 项目介绍 【1】开发背景 【2】研究的意义 【3】最终实现需求 【4】项目硬件模块组成 1.2 设计思路 【1】整体设计思路 【2】上位机开发思路 1.3 项目开发背景 【1】选题的意义 【2】摘要 【3】国内外相关研究现状 【5】参考文献 1.4 开发工具的选择 【1】…

电脑如何安装win10专业版_电脑用u盘安装win10专业版教程

电脑如何安装win10专业版&#xff1f;电脑还是建议安装win10专业版。Win分为多个版本&#xff0c;其中家庭版&#xff08;Home&#xff09;和专业版&#xff08;Pro&#xff09;是用户选择最多的两个版本。win10专业版在功能以及安全性方面有着明显的优势&#xff0c;所以电脑还…

多语言文本 AI 情感分析 API 数据接口

多语言文本 AI 情感分析 API 数据接口 AI / 文本处理 AI 模型快速分析文本情感倾向 多语言文本 / 情感分析。 1. 产品功能 支持多语言文本情感分析&#xff1b;基于特定 AI 模型&#xff0c;快速识别文本情感倾向&#xff1b;适用于评论分析、舆情监控等场景&#xff1b;全接…

【R语言】R语言的工作空间映像(workspace image,通常是.RData)详解

R语言的工作空间映像&#xff08;.RData&#xff09;详解 在使用 R 语言时&#xff0c;你可能会注意到&#xff0c;每次退出 R 会弹出一个提示&#xff1a; Save workspace image? [y/n/c] 如果你使用的是 Rstudio 这个 IDE 来进行R语言的开发&#xff0c;那么可能弹出的提示…

在线 A2C实践

在线 A2C&#xff08;Actor-Critic&#xff09;算法在推荐系统中的实践&#xff0c;核心是将推荐过程建模为实时交互的强化学习问题&#xff0c;通过 Actor 生成推荐策略、Critic 评估策略价值&#xff0c;实现 “决策 - 反馈 - 更新” 的闭环。从样本设计到最终上线&#xff0…

Eclipse RCP产品动态模块设计

文章目录 遇到问题具体实践效果演示应用下载 遇到问题 如果你是一个To C产品的设计者&#xff0c;势必会遇到用户需求高度分化的场景&#xff0c;随之而来的是繁杂的功能列表&#xff0c;如何让用户只接触与其任务直接相关的功能&#xff0c;隐藏无关元素&#xff1f; 具体实…

NLP自然语言处理: FastText工具与迁移学习基础详解

FastText工具与迁移学习基础详解 一、知识框架总览 FastText工具核心功能与应用场景FastText模型架构与工作原理层次Softmax加速机制哈夫曼树概念与构建方法 二、FastText工具核心解析 2.1 功能定位 双重核心功能 文本分类&#xff1a;可直接用于文本分类任务&#xff0c;快速生…

uni-app 生命周期详解

概述 uni-app 基于 Vue.js 框架开发&#xff0c;其生命周期包含了三个层面&#xff1a; 应用生命周期&#xff1a;App.vue 的生命周期页面生命周期&#xff1a;各个页面的生命周期Vue 组件生命周期&#xff1a;Vue.js 原生的组件生命周期 这三种生命周期在不同场景下会按特定顺…

MCU外设初始化:为什么参数配置必须优先于使能

在微控制器领域&#xff0c;初始化参数配置阶段至关重要。此时&#xff0c;虽无电源驱动&#xff0c;但微控制器在使能信号到来前&#xff0c;借初始化参数配置这一精细步骤&#xff0c;开启关键准备进程。初始化参数配置如同物理坐标锚定、逻辑指令部署、内在秩序预设&#xf…

AI一周事件(2025年8月6日-8月12日)

&#xff08;以下借助 DeepSeek-R1 & ChatGPT-5 辅助整理&#xff09; 一、AI 模型与算法进展 1. OpenAI 正式发布 GPT-5&#xff08;8月7日&#xff09; 事件&#xff1a;OpenAI 于 2025 年 8 月 7 日推出 GPT-5——其自称拥有“PhD 级别”的智能&#xff0c;通过内置…