Python题解Leetcode Hot100之二叉树

news2024/12/24 21:04:46

1. 二叉树的中序遍历

  • 题目描述
    给定一个二叉树,返回它的中序遍历。
  • 解题思路
    使用递归的方法对左子树进行中序遍历,然后访问根节点,最后对右子树进行中序遍历。也可以使用栈来模拟递归的过程,迭代地进行中序遍历。
  • 代码
    class Solution:
        def inorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
            path = []
            def dfs(node):
                nonlocal path
                if not node:
                    return 
                dfs(node.left)
                path.append(node.val)
                dfs(node.right)
            dfs(root)
            return path
    

2. 二叉树的最大深度

  • 题目描述
    给定一个二叉树,找出其最大深度。最大深度是从根节点到最远叶子节点的最长路径上的节点数。
  • 解题思路
    使用递归方法计算左右子树的最大深度,然后取最大值加一。也可以使用广度优先搜索(BFS)遍历树的每一层,记录层数。
  • 代码
    class Solution:
        def maxDepth(self, root: Optional[TreeNode]) -> int:
            if not root:
                return 0
            left = self.maxDepth(root.left)
            right = self.maxDepth(root.right)
            return max(left, right) + 1
    

3. 翻转二叉树

  • 题目描述
    镜像翻转一棵二叉树。
    在这里插入图片描述

  • 解题思路
    可以看到翻转二叉树就是对所有节点的左右节点进行翻转,因此使用递归方法交换每个节点的左右子节点。

  • 代码

    class Solution:
        def invertTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
            if not root:
                return None
            invert_left = self.invertTree(root.left)
            invert_right = self.invertTree(root.right)
            
            root.left, root.right = invert_right, invert_left
            return root
    

4. 对称二叉树

  • 题目描述
    给定一个二叉树,检查它是否是镜像对称的。
    在这里插入图片描述

  • 解题思路
    观察发现二叉树对称就是,比较左节点的左节点和右节点的右节点是否相同,左节点的右节点和右节点的左节点是否相同。此题特殊在需要写一个辅助函数,输入是两个节点,并从root.left和root.right开始递归

  • 代码

    class Solution:
        def isSymmetric(self, root: Optional[TreeNode]) -> bool:
            def symmetric(left, right):
                if not left and not right:
                    return True
                if not left or not right:
                    return False
                if left.val != right.val:
                    return False
                return symmetric(left.left, right.right) and symmetric(left.right, right.left)
            return symmetric(root.left, root.right)
    

5. 二叉树的直径

  • 题目描述
    给定一棵二叉树,计算它的直径。二叉树的直径是树中任意两个节点路径长度中的最大值。
  • 解题思路
    使用递归方法计算每个节点的左右子树深度,然后更新最大直径。每个节点的直径是左右子树深度之和,注意直径的定义是边的数量而不是节点数。
  • 代码
    class Solution:
        def diameterOfBinaryTree(self, root: Optional[TreeNode]) -> int:
            res = 0
            def max_height(root):
                nonlocal res
                if not root:
                    return 0
                left = max_height(root.left)
                right = max_height(root.right)
                res = max(res, left + right)
                return max(left, right) + 1
            max_height(root)
            return res
    

6. 二叉树的层序遍历

  • 题目描述
    给定一个二叉树,返回其按层次遍历的节点值。即逐层地,从左到右访问所有节点。
  • 解题思路
    使用队列进行广度优先搜索(BFS),逐层访问每个节点,并将节点值存入结果列表。注意在将读取的每个节点的左右节点压入队列的时候,要记得判断左右节点是不是None;
  • 代码
    class Solution:
        def levelOrder(self, root: Optional[TreeNode]) -> List[List[int]]:
            if not root:
                return []
            que = deque()
            que.append(root)
            res = []
            while len(que) != 0:
                cur_level = []
                n = len(que)
                for i in range(n):
                    node = que.popleft()
                    cur_level.append(node.val)
                    # 注意要判断节点是不是None,避免将None加入到que
                    if node.left:
                        que.append(node.left)
                    if node.right:
                        que.append(node.right)
                res.append(cur_level)
            return res
    

7. 将有序数组转换为二叉搜索树

  • 题目描述
    将一个按照升序排序的有序数组转换为一棵高度平衡的二叉搜索树。
  • 解题思路
    使用递归方法,每次选择中间元素作为根节点,左右子数组分别作为左右子树,递归构造二叉搜索树。
  • 代码
    class Solution:
        def sortedArrayToBST(self, nums: List[int]) -> Optional[TreeNode]:
            n = len(nums)
            if n == 0:
                return None
            if n == 1:
                return TreeNode(val = nums[0])
            mid = n // 2
            node = TreeNode(val = nums[mid])
            node.left = self.sortedArrayToBST(nums[: mid])
            node.right = self.sortedArrayToBST(nums[mid+1: ])
            return node
    

8. 验证二叉搜索树

  • 题目描述
    给定一个二叉树,判断其是否是一个有效的二叉搜索树(BST)。
  • 解题思路
    ==二叉搜索树的性质:中序遍历是有序的。==因此对二叉搜索树进行中序遍历,利用一个全局变量来记录上一节点的值,这样遍历所有节点并检查节点值是否严格递增。
  • 代码
    class Solution:
        def isValidBST(self, root: Optional[TreeNode]) -> bool:
            # 设置全局变量,用于记录上一个节点的值
            last_val = float("-inf")
        	# 中序遍历
            def inorder(root):
                nonlocal last_val
                
                if not root:
                    return True
                # 查验左子树是不是二叉搜索树
                left = inorder(root.left)
                # 查验当前节点
                if root.val <= last_val:
                    return False
                last_val = root.val
                # 查验右子树
                right = inorder(root.right)
                return left and right
    
            return inorder(root)
    

9. 二叉搜索树中第K小的元素

  • 题目描述
    给定一个二叉搜索树,编写一个函数 kthSmallest 来查找其中第 k 个最小的元素。
  • 解题思路
    依然是利用二叉搜索树的性质,使用中序遍历二叉搜索树,计数遍历到第 k 个节点时,即为第 k 小的元素。
  • 代码
class Solution:
	def kthSmallest(self, root: Optional[TreeNode], k: int) -> int:
	        def dfs(root):
	            if not root: return
	            dfs(root.left)
	            if self.k == 0: return
	            self.k -= 1
	            if self.k == 0: self.res = root.val
	            dfs(root.right)
	
	        self.k = k
	        dfs(root)
	        return self.res

10. 二叉树的右视图

  • 题目描述
    给定一棵二叉树,想象自己站在它的右侧,按从顶部到底部的顺序,返回看到的节点值。
  • 解题思路
    使用广度优先搜索(BFS),逐层记录最后一个节点的值。
  • 代码
    class Solution:
        def rightSideView(self, root: Optional[TreeNode]) -> List[int]:
            if not root:
                return []
            que = deque()
            que.append(root)
            res = []
            while len(que) != 0:
                n = len(que)
                for i in range(n):
                    node = que.popleft()
                    if i == n - 1:
                        res.append(node.val)
                    if node.left:
                        que.append(node.left)
                    if node.right:
                        que.append(node.right)
            return res
    

11. 二叉树展开为链表

  • 题目描述
    给定一个二叉树,原地将它展开为一个单链表,链表的顺序和先序遍历相同。
    在这里插入图片描述

  • 解题思路
    对二叉树进行先序遍历,然后把遍历到的节点依次连接起来,使用一个全局变量记录上一个节点;

  • 代码

    class Solution:
        def flatten(self, root: Optional[TreeNode]) -> None:
            """
            Do not return anything, modify root in-place instead.
            """
            if not root:
                return
            dummy_root = TreeNode()
            prev = dummy_root
            def dfs(node):
                nonlocal prev
                if not node:
                    return 
                # 这里要先吧left和right保存下来
                left = node.left
                right = node.right
                prev.right = node
                prev.left = None
                prev = node
                dfs(left)
                dfs(right)
            dfs(root)
    

12. 从前序与中序遍历序列构造二叉树

  • 题目描述
    根据一棵树的前序遍历与中序遍历构造二叉树。
  • 解题思路
    使用递归方法,前序遍历的第一个元素为根节点,根据根节点的值找到中序遍历中根节点的位置,然后就能根据中序遍历分割左右子树的节点,将两个遍历分成左右两部分,递归构造二叉树。
  • 代码
class Solution:
    def buildTree(self, preorder: List[int], inorder: List[int]) -> Optional[TreeNode]:
        if len(preorder) == 0:
            return None
        if len(preorder) == 1:
            return TreeNode(val=preorder[0])
        root_val = preorder[0]
        # 在中序遍历中从下标为0开始寻找
        i = 0
        while inorder[i] != root_val:
            i += 1
        root = TreeNode(root_val)
        root.left = self.buildTree(preorder[1:i+1], inorder[:i])
        root.right = self.buildTree(preorder[i+1:], inorder[i+1:])
        return root

13. 路径总和 III

  • 题目描述
    给定一个二叉树,它的每个节点都存放一个整数值。找出路径和等于给定数值的路径总数。路径不需要从根节点开始,也不需要在叶子节点结束,但是路径方向必须是向下的(只能从父节点到子节点)。
    在这里插入图片描述

  • 解题思路
    使用双重递归,外层递归遍历每个节点,内层递归计算以当前节点为起点的路径数。

  • 代码

    class Solution:
        def pathSum(self, root: Optional[TreeNode], targetSum: int) -> int:
            res = 0
            # 计算以当前节点为起点的路径数
            def backtrace(node, s, targetSum):
                nonlocal res
                if not node:
                    return 
                s += node.val
                if s == targetSum:
                    res += 1
                backtrace(node.left, s, targetSum)
                backtrace(node.right, s, targetSum)
                s -= node.val
            # 递归遍历每个节点
            def dfs(root, targetSum):
                if not root:
                    return 
                backtrace(root, 0, targetSum)
                dfs(root.left, targetSum)
                dfs(root.right, targetSum)
            dfs(root, targetSum)
            return res
    

14. 二叉树的最近公共祖先

  • 题目描述
    给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。
  • 解题思路
    使用递归方法,如果当前节点为目标节点之一或为空,则返回当前节点;否则,递归查找左右子树的最近公共祖先。如果左右子树都找到目标节点,则当前节点为最近公共祖先。
  • 代码
    class Solution:
        def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
            if not root:
                return root
            if root == p or root == q:
                return root
            left = self.lowestCommonAncestor(root.left, p, q)
            right = self.lowestCommonAncestor(root.right, p, q)
            if left and right:
                return root
            if left:
                return left
            if right:
                return right
            return None
    

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

  • 题目描述
    给定一个非空二叉树,返回其最大路径和。路径被定义为一条从树中任意节点出发,沿父节点-子节点连接,达到任意节点的序列。该路径至少包含一个节点,且不一定经过根节点。

  • 解题思路
    经过某个节点cur的最大路径和 = cur.val + max(cur.left起始的路径最大和, 0) + max(cur.right起始的路径最大和,0)。使用双层递归,内层递归求以当前节点为起始节点的路径最大和,外层递归遍历所有节点,根据上面的公式求取最终结果;

  • 代码

    class Solution:
        def maxPathSum(self, root: Optional[TreeNode]) -> int:
        	# 求以当前节点为起始节点的路径最大和
            def backtrace(root):
                if not root:
                    return 0
                left = backtrace(root.left)
                right = backtrace(root.right)
                if left <= 0 and right <= 0:
                    return root.val
                return root.val + max(left, right)
            # 外层递归遍历所有节点,根据上面的公式求取最终结果
            def dfs(root):
                nonlocal res
                if not root:
                    return
                left = backtrace(root.left)
                right = backtrace(root.right)
                cur = root.val
                if left > 0:
                    cur += left
                if right > 0:
                    cur += right
                res = max(cur, res)
                dfs(root.left)
                dfs(root.right)
            res = float("-inf")
            dfs(root)
            return res  
    

16. 总结

  • 递归分解成子问题
    这一类问题可以递归将一个二叉树分解成左右子树,分别进行相同的问题求解,依次类推;这类问题包括二叉树的最大深度、翻转二叉树、对称二叉树
  • 二叉搜索树
    重要性是中序遍历是升序的
  • 层序遍历
    队列

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

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

相关文章

机器人控制系列教程之Delta机器人运动学分析(1)

并联机构运动学 对于并联机构的位置正解、位置逆解和对应于位置解的速度、加速度进行分析是并联机构运动学分析主要内容。与串联机构不同&#xff0c;一般并联机构的位置逆解相对要简单&#xff0c;而位置正解则求解比较复杂些。并联机构的位置正解的求解过程中&#xff0c;大…

云徙电商OMS如何赋能品牌电商业务精细化运营

「6.18」、「双十一」、「双十二「、「年货节」等等&#xff0c;如火如荼的「造节」&#xff0c;将电商不断推向高地。 关于电商业务&#xff0c;一个业内共识是&#xff0c;2003 年是线上线下业务切换的关键节点。而消费者需求的变迁是引发这场业务模式革新的核心推手。 盘点…

Crossover和PD虚拟机谁更强大?pd虚拟机一年多少钱

在当前的虚拟化技术和应用程序兼容性解决方案中&#xff0c;Crossover和PD虚拟机&#xff08;Parallels Desktop&#xff09;都是备受用户喜爱的选择。对于需要在非原生系统上运行应用程序的用户而言&#xff0c;选择合适的工具尤为重要。那么&#xff0c;Crossover和PD虚拟机谁…

d3dx9_43.dll丢失怎么解决?d3dx9_43.dll怎么安装详细教程

在使用计算机中&#xff0c;如果遇到d3dx9_43.dll丢失或许找不到d3dx9_43.dll无法运行打开软件怎么办&#xff1f;这个是非常常见问题&#xff0c;下面我详细介绍一下d3dx9_43.dll是什么文件与d3dx9_43.dll的各种问题以及d3dx9_43.dll丢失的多个解决方法&#xff01; 一、d3dx9…

vue3+ts 写echarts 中国地图

需要引入二次封装的echarts和在ts文件写的option <template><div class"contentPage"><myEcharts :options"chartOptions" class"myEcharts" id"myEchartsMapId" ref"mapEcharts" /></di…

vscode语言模式

1.背景 写vue3ts项目的时候&#xff0c;用到了volar插件&#xff0c;在单文件使用的时候&#xff0c;鼠标悬浮在代码上面会有智能提示&#xff1b; 但是最近volar插件提示被弃用了&#xff0c;然后我按照它的官方提示&#xff0c;安装了Vue-official扩展插件&#xff0c;但是…

【开发篇】明明配置跨域声明,为什么却仍可以发送HTTP请求

一、问题 在SpringBoot项目中&#xff0c;明确指定仅允许指定网站跨域访问&#xff1a; 为什么开发人员却仍旧可以通过HTTP工具调用接口&#xff1f; 二、为什么 在回答这个问题之前&#xff0c;我们首先要了解一下什么是CORS&#xff01; 1、什么是CORS CORS的全称为跨域资源…

20240702在飞凌OK3588-C开发板上通过HDMI OUT输出USB3.0接口的热像仪的预览图像

20240702在飞凌OK3588-C开发板上通过HDMI OUT输出USB3.0接口的热像仪的预览图像 2024/7/2 18:19 rootok3588:/# rootok3588:/# rootok3588:/# lsusb Bus 005 Device 001: ID 1d6b:0002 Bus 003 Device 001: ID 1d6b:0001 Bus 001 Device 001: ID 1d6b:0002 Bus 006 Device 00…

普发PfeifferTC400真空泵驱动操作手侧引脚定义通讯定义

普发PfeifferTC400真空泵驱动操作手侧引脚定义通讯定义

shellhub 部署

1、环境介绍 操作系统&#xff1a;龙蜥os 7.9 2、安装docker yum install -y yum-utils device-mapper-persistent-data lvm2 yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo sed -i sdownload.docker.commirrors.aliyun.c…

美的、希亦、苏泊尔超声波清洗机值不值得买?对比测评甄选性能王!

超声波清洗机作为一种高效、便捷的清洁设备&#xff0c;不仅可以用于清洗眼镜&#xff0c;还可以用于清洗化妆刷、珠宝、手表等多种物品&#xff0c;极大的方便了日常生活。其高频振动的特点可以帮助去除物品表面的污垢和细菌&#xff0c;让物品焕然一新。因此&#xff0c;选择…

YOLOv8改进 | 卷积模块 | 减少冗余计算和内存访问的PConv【CVPR2023】

秋招面试专栏推荐 &#xff1a;深度学习算法工程师面试问题总结【百面算法工程师】——点击即可跳转 &#x1f4a1;&#x1f4a1;&#x1f4a1;本专栏所有程序均经过测试&#xff0c;可成功执行&#x1f4a1;&#x1f4a1;&#x1f4a1; 专栏目录 &#xff1a;《YOLOv8改进有效…

最小步数模型——AcWing 1107. 魔板

最小步数模型 定义 最小步数模型通常是指在某种约束条件下&#xff0c;寻找从初始状态到目标状态所需的最少操作或移动次数的问题。这类问题广泛存在于算法、图论、动态规划、组合优化等领域。具体来说&#xff0c;它涉及确定一个序列或路径&#xff0c;使得按照特定规则执行…

【JS】纯web端使用ffmpeg实现的视频编辑器-视频合并

纯前端实现的视频合并 接上篇ffmpeg文章 【JS】纯web端使用ffmpeg实现的视频编辑器 这次主要添加了一个函数&#xff0c;实现了视频合并的操作。 static mergeArgs(timelineList) {const cmd []console.log(时间轴数据,timelineList)console.log("文件1",this.readD…

BAS(入侵与攻击模拟)正在替代红队测试?

之前经常会被用户问到&#xff0c;漏扫、渗透和红队红的区别是啥&#xff1f; 传统的漏扫、渗透和红蓝对抗&#xff0c;可以看到工具化的漏洞不可靠&#xff0c;人工的成本就高。怎么找到一个漏洞可信度又高&#xff0c;成本又低的&#xff0c;就诞生了BAS。 抛开漏扫&#xf…

多商户b2b2c商城系统怎么运营

B2B2C多用户商城系统支持多种运营模式&#xff0c;以满足不同类型和发展阶段的企业需求。以下是五大主要的运营模式&#xff1a; **1. 自营模式&#xff1a;**平台企业通过建立自营线上商城&#xff0c;整合自身多渠道业务。通过会员、商品、订单、财务和仓储等多用户商城管理系…

windows自带的性能采集配置方法

1 计算机---右键---管理 2 性能--数据收集器几---用户自定义 3新建--输入程序名称 并在此页面选择--手动创建&#xff08;高级&#xff09; 4 下一步--勾选性能计数器---下一步 5 添加--找到process Processor Time User Time Handle Count ID Process Private Bytes…

Java8新特性之Optional、Lambda表达式、Stream、新日期Api使用总结

标题 Optional类常用Api使用说明Optional API 使用建议 Lambda表达式Lambda 表达式的局限性与解决方案 Stream案例实操优化 Stream 操作 新的日期和时间APILocalDateTime在SpringBoot中的应用 函数式接口&#xff08;Functional&#xff09; Optional博客参考地址1 Stream博客参…

核心实验:基于Web前端的性能测试分析!

实验简介 本实验主要利用IE和Chrome的F12开发人员工具结合Web前端测试分析相关知识&#xff0c;对常见网站进行基于前端的性能测试分析&#xff0c;本实验将不会使用到测试开发相关技术&#xff0c;而是纯粹意义上的手工测试&#xff0c;但却是很容易找到系统前端性能及设计问…

什么是继电器测试负载箱?

继电器测试负载箱专门用于测试继电器性能的设备&#xff0c;它能够模拟各种实际工况下的负载&#xff0c;以便对继电器进行全面、准确的性能评估。继电器是一种广泛应用于电力系统、自动化控制系统等领域的关键元件&#xff0c;其主要功能是在输入信号的控制下&#xff0c;实现…