二刷力扣--二叉树(3)

news2024/12/24 2:33:02

106.从中序与后序遍历序列构造二叉树

给定两个整数数组 inorderpostorder ,其中 inorder 是二叉树的中序遍历, postorder 是同一棵树的后序遍历,请你构造并返回这颗 二叉树

手动构造的步骤:
后序确定根,中序分左右(子树)。
后序数组的最后一个元素(根)为切割点,先切中序数组,根据中序数组,反过来再切后序数组。一层一层切下去,每次后序数组最后一个元素就是节点元素。
在这里插入图片描述

class Solution:
    def buildTree(self, inorder: List[int], postorder: List[int]) -> Optional[TreeNode]:
        def traversal(inorder, postorder):
            if not postorder:
                return None
            
            # 根
            rootValue = postorder[-1]
            root = TreeNode(rootValue)
            # 叶子
            if len(postorder) == 1:
                return root
            
            #3. 找切割点
            inorder_index = inorder.index(rootValue)
            # 4. 切割 inorder 左、右
            leftInorder = inorder[:inorder_index] 
            rightInorder = inorder[inorder_index+1:]
            # 5. 切割 postoder 左、右
            postorder = postorder[:-1]
            leftPostorder = postorder[:len(leftInorder)]
            rightPostorder = postorder[len(leftInorder):]
            # 6. 递归处理
            root.left = traversal(leftInorder, leftPostorder)
            root.right = traversal(rightInorder, rightPostorder)

            return root

        if len(inorder) == 0 or len(postorder)==0:
            return None
        root = traversal(inorder, postorder)
        return root

654.最大二叉树

给定一个不重复的整数数组 nums最大二叉树 可以用下面的算法从 nums 递归地构建:

  1. 创建一个根节点,其值为 nums 中的最大值。
  2. 递归地在最大值 左边子数组前缀上 构建左子树。
  3. 递归地在最大值 右边子数组后缀上 构建右子树。

返回 nums 构建的 最大二叉树

递归公式:

  1. 函数参数和返回值
    参数:待构建数组nums。
    返回值:通过nums构建的树的根节点root
  2. 终止条件
    nums为空,无法继续构建。
  3. 单层逻辑
    按照题目的描述。选出最大值,递归左右子树。
class Solution:
    def constructMaximumBinaryTree(self, nums: List[int]) -> Optional[TreeNode]:
        def construct(nums):
            if not nums:
                return None
            max_value = max(nums)
            max_index = nums.index(max_value)
            root = TreeNode(max_value)
            
            left_nums = nums[:max_index]
            right_nums = nums[max_index+1:]

            root.left = construct(left_nums)
            root.right = construct(right_nums)

            return root
        return construct(nums)

(可以优化一下参数,每次不用传nums,而是传数组的左右边界)

617.合并二叉树

合并的规则是:如果两个节点重叠,那么将这两个节点的值相加作为合并后节点的新值;否则,不为 null 的节点将直接作为新二叉树的节点。

递归公式:

  1. 函数参数和返回值
    参数:两棵树的节点 t1, t2
    返回值:合并后的节点
  2. 终止条件:
    t1,t2其中一个为None,则直接返回另一个。
  3. 单层逻辑
    (t1,t2都不为None),两个节点值相加,并递归左右子树。
class Solution:
    def mergeTrees(self, root1: Optional[TreeNode], root2: Optional[TreeNode]) -> Optional[TreeNode]:
        def helper(t1, t2):
            if t1 is None:
                return t2
            if t2 is None:
                return t1
            t1.val += t2.val
            t1.left = helper(t1.left, t2.left)
            t1.right = helper(t1.right, t2.right)
            return t1
        return helper(root1, root2)

700.二叉搜索树中的搜索

在二叉搜索树中找值为val的节点。

利用二叉树的性质(左<根<右)

递归公式:

  1. 参数:当前节点t。 返回值:节点或None
  2. 终止条件:t为空
  3. 单层逻辑:t.val == val,返回。t.val < val ,递归右子树。t.val > val ,递归左子树。
class Solution:
    def searchBST(self, root: Optional[TreeNode], val: int) -> Optional[TreeNode]:
        def helper(t):
            if t is None:
                return None
            if t.val == val:
                return t

            if t.val < val:
                return helper(t.right)
            else:
                return helper(t.left)
        
        return helper(root)

98.验证二叉搜索树

利用二叉树的性质(左<根<右),中序遍历的结果是一个递增的序列。

class Solution:
    def isValidBST(self, root: Optional[TreeNode]) -> bool:   
        def inorder(t):
            if t is None:
                return
            inorder(t.left)
            nums.append(t.val)
            inorder(t.right)

        nums = []
        inorder(root)
        return all(nums[i]<nums[i+1] for i in range(len(nums)-1))

530.二叉搜索树的最小绝对差

给你一个二叉搜索树的根节点 root ,返回 树中任意两不同节点值之间的最小差值

上面说过,二叉搜索树的中序遍历是一个递增 的,所以差值最小的两个节点一定是在中序遍历过程的相邻的两个节点。

class Solution:
    def getMinimumDifference(self, root: Optional[TreeNode]) -> int:
        def inorder(t):
            if t is None:
                return 
            
            inorder(t.left)
            nums.append(t.val)
            inorder(t.right)
        nums = []
        inorder(root)
        return min(nums[i+1] - nums[i]  for i in range(len(nums) - 1) )

501.二叉搜索树中的众数

给你一个含重复值的二叉搜索树(BST)的根节点 root ,找出并返回 BST 中的所有 众数(即,出现频率最高的元素)。

假定 BST 满足如下定义:

  • 结点左子树中所含节点的值 小于等于 当前节点的值
  • 结点右子树中所含节点的值 大于等于 当前节点的值
  • 左子树和右子树都是二叉搜索树
class Solution:
    def findMode(self, root: Optional[TreeNode]) -> List[int]:
        def inorder(t):
            if t is None:
                return 
            yield from inorder(t.left)
            yield t.val
            yield from inorder(t.right)
        nums = inorder(root)
        res = []
        max_times = 1
        cur_times = 1
        pre = -10**6
        for i, num in enumerate(nums):
            if num == pre:
                cur_times += 1
            else:
                pre = num 
                cur_times = 1
                
            if cur_times > max_times:
                max_times = cur_times
                res = [num]
            elif cur_times == max_times:
                res.append(num)

	        return res

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

给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。

我们希望从下往上找两个节点的最近公共祖先,那么二叉树的后序遍历(左右中)就可以实现从下到上的顺序。

递归公式:

  1. 函数参数:当前节点root, 需要匹配的节点p, q
    返回值:如果当前节点是p/q祖先,则返回该节点。如果返回值为空,则表示没找到。
  2. 终止条件:
    当前节点为空或则和p/q匹配,则返回root。
  3. 单层逻辑
    递归处理left和right。
    如果left和right都不为空,则root为最近公共祖先。
    如果left和right只有一个不为空,则返回不为空的那个。
    如果left和right都为空,则返回None。
class Solution:
    def lowestCommonAncestor(self, root, p, q):
        if root == q or root == p or root is None:
            return root

        left = self.lowestCommonAncestor(root.left, p, q)
        right = self.lowestCommonAncestor(root.right, p, q)

        if left  and right:
            return root

        if left is None and right:
            return right
        elif left  and right is None:
            return left
        else: 
            return None

235. 二叉搜索树的最近公共祖先

这次找最近公共祖先可以从上到下找了。因为二叉搜索树满足(左<根<右),所以如果root的值在p,q之间,则说明root是p,q的公共祖先(并且是最近的)。
递归公式:

  1. 参数:当前节点t
    返回值:当前节点t
  2. 终止条件:当前节点为None
  3. 单层逻辑:如果 t.val 比p,q的值都小,则说明该去右子树找;
    如果 t.val 比p,q的值都大,则说明该去左子树找;
    否则说明t就是p,q的分叉点,p,q一个在左,一个在右,t就是p,q的最近公共祖先,返回t。
class Solution:
    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
        def helper(t):
            if t is None:
                return 
            if t.val > p.val and t.val > q.val:
                return helper(t.left)
            elif t.val < p.val and t.val < q.val:
                return helper(t.right)
            else:
                return t
        return helper(root)

701.二叉搜索树中的插入操作

给定二叉搜索树(BST)的根节点 root 和要插入树中的值 value ,将值插入二叉搜索树。 返回插入后二叉搜索树的根节点。 输入数据 保证 ,新值和原始二叉搜索树中的任意节点值都不同。

在二叉树找到空节点插入新数据,不需要调整二叉树结构。
递归公式:

  1. 参数:当前节点root,待插入的值val
    返回值:root
  2. 终止条件:root 为None,创建值为val的节点node并返回node
  3. 单层逻辑:
    if root.val > val, 递归左子树root.left = self.insertIntoBST(root.left, val)
    if root.val < val, 递归右子树root.right = self.insertIntoBST(root.right, val)
    返回root
class Solution:
    def insertIntoBST(self, root: Optional[TreeNode], val: int) -> Optional[TreeNode]:
        if not root:
            node = TreeNode(val)
            return node
        if root.val > val:
            root.left = self.insertIntoBST(root.left, val)
        if root.val < val:
            root.right = self.insertIntoBST(root.right, val)
        
        return root

450.删除二叉搜索树中的节点

删除二叉搜索树的节点,需要调整树的结构。

递归公式:

  1. 函数参数: 当前节点root, 待插入值key。
    返回值:返回删除后节点后的根节点。
  2. 终止条件: 当前节点为空,返回None
  3. 单层逻辑
    3.1 如果找到节点(if root.val == key),删除节点并调整结构。
    3.2 没找到节点,则递归查找。
if root.val > key:
	root.left = self.deleteNode(root.left, key)
if root.val < key:
	root.right = self.deleteNode(root.right, key)

3.3 返回root

其中3.1 删除节点可能遇到多种情况:

  1. 当前节点没有子节点了,直接删除,返回None
  2. 当前节点只有单侧节点(左/右),直接删除,返回左/右节点
  3. 左右节点都有,需要将左子树挂在右子树的最左下角,然后删除节点,返回右节点。
    (不需要显式删除节点)
class Solution:
    def deleteNode(self, root: Optional[TreeNode], key: int) -> Optional[TreeNode]:
        if root is None:
            return None
        if root.val == key:
            if root.left is None and root.right is None:
                return None
            elif root.left is None:
                return root.right
            elif root.right is None:
                return root.left
            else: # 左右都不为空时, 将 左子树 挂在右子树的最左下角
                cur = root.right
                while cur.left :
                    cur = cur.left
                cur.left = root.left  
                return  root.right
        if root.val > key:
            root.left = self.deleteNode(root.left, key)
        if root.val < key:
            root.right = self.deleteNode(root.right, key)
        return root

669. 修剪二叉搜索树

给你二叉搜索树的根节点 root ,同时给定最小边界low 和最大边界 high。通过修剪二叉搜索树,使得所有节点的值在[low, high]中。

class Solution:
    def trimBST(self, root: Optional[TreeNode], low: int, high: int) -> Optional[TreeNode]:
        def helper(t):
            # 终止条件
            if t is None:
                return None
            
            # 单层逻辑
            # 1.如果根<low,则(删除根和左孩子),处理右孩子并返回
            if t.val < low:
                right = helper(t.right)
                return right
            # 2.同理,如果根>high,则(删除根和右孩子),处理左孩子并返回
            if t.val > high:
                left = helper(t.left)
                return left
            # 3.如果结点的值位于区间 [low,high]
            # 递归处理左,右子树
            t.left = helper(t.left)
            t.right = helper(t.right)
            return t
        return helper(root)

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

给你一个整数数组 nums ,其中元素已经按 升序 排列,请你将其转换为一棵 高度平衡 二叉搜索树。

数组构造二叉树,构成平衡树是自然而然的事情,因为大家默认都是从数组中间位置取值作为节点元素,一般不会随机取。所以想构成不平衡的二叉树是自找麻烦

class Solution:
    def sortedArrayToBST(self, nums: List[int]) -> Optional[TreeNode]:
        def helper(left, right):
            if left > right:
                return None
            mid = left + (right-left)//2
            root = TreeNode(nums[mid])
            root.left = helper(left,mid-1)
            root.right = helper(mid+1, right)
            return root
        return helper(0, len(nums)-1)

538.把二叉搜索树转换为累加树

给出二叉 搜索 树的根节点,该树的节点值各不相同,请你将其转换为累加树(Greater Sum Tree),使每个节点 node 的新值等于原树中大于或等于 node.val 的值之和。

二叉搜索树满足左<根<右,所以为了知道比node值大的节点,需要按照 右,根,左的顺序访问(累加)。

class Solution:
    def convertBST(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
        pre = 0 # 非局部变量pre,记录上一个(修改过的)节点的值
        def traversal(cur):
            nonlocal pre
            if cur is None:
                return 
            # 右
            traversal(cur.right)
            # 根
            cur.val += pre
            pre = cur.val
            # 左
            traversal(cur.left)
        traversal(root)
        return root

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

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

相关文章

面试必杀技:Jmeter性能测试攻略大全(第一弹)

前言 性能测试是一个全栈工程师/架构师必会的技能之一&#xff0c;只有学会性能测试&#xff0c;才能根据得到的测试报告进行分析&#xff0c;找到系统性能的瓶颈所在&#xff0c;而这也是优化架构设计中重要的依据。 第一章 测试流程&#xff1a; 需求分析→环境搭建→测试…

上位机通过Modbus转Profinet网关与变频器Modbus通讯案例

上位机与变频器Modbus通讯是通过Modbus转Profinet网关来实现的。这个网关可以理解为一个通信翻译器&#xff0c;负责将上位机通过Modbus协议发送的数据转换为Profinet协议&#xff0c;再通过Profinet网络与变频器进行通信。 上位机通过Modbus转Profinet网关与变频器Modbus通讯…

操作系统存储管理

目录 存储管理&#xff08;1&#xff09; 第一节 存储管理概述&#xff08;内存管理&#xff09; 一、存储体系 二、存储管理的任务 三、地址转换 存储管理&#xff08;2&#xff09; 第二节 分区管理方案 一、固定分区 二、可变分区 三、分区管理方案的优缺点 第…

基于Web的足球青训俱乐部管理后台系统的设计与开发

目录 前言 一、技术栈 二、系统功能介绍 三、核心代码 1、登录模块 2、文件上传模块 3、代码封装 前言 随着社会经济的快速发展&#xff0c;人们对足球俱乐部的需求日益增加&#xff0c;加快了足球健身俱乐部的发展&#xff0c;足球俱乐部管理工作日益繁忙&#xff0c;传统…

安果清理大师-不用的时候我真的不给你推荐这种软件

下载地址&#xff1a;安果移动 视频演示&#xff1a;安果清理大师-不用的时候我真的不给你推荐这种软件_哔哩哔哩_bilibili 全能手机助手&#xff1a;四大功能&#xff0c;全面呵护您的手机&#xff01;☆ 在如今的数字时代&#xff0c;手机已经成为我们生活中不可或缺 的伴侣…

1795_ChibiOS网络书籍阅读_实时系统的一些概念

全部学习汇总&#xff1a; GreyZhang/g_ChibiOS: I found a new RTOS called ChibiOS and it seems interesting! (github.com) 不同的OS在介绍自己的机理的时候都有自己的模型或者抽象概念&#xff0c;ChibiOS也不例外。这里的几个概念需要做一个基本的理解&#xff1a; 1. 进…

如何使用Selenium进行自动化测试

前言 对于很多刚入门的测试新手来说&#xff0c;大家都将自动化测试作为自己职业发展的一个主要阶段。可是&#xff0c;在成为一名合格的自动化测试工程师之前&#xff0c;我们不仅要掌握相应的理论知识&#xff0c;还要进行大量的实践&#xff0c;积累足够的经验&#xff0c;…

RGB格式

Qt视频播放器实现&#xff08;目录&#xff09; RGB的使用场景 目前&#xff0c;数字信号源&#xff08;直播现场的数字相机采集的原始画面&#xff09;和显示设备&#xff08;手机屏幕、笔记本屏幕、个人电脑显示器屏幕&#xff09;使用的基本上都是RGB格式。 三原色 RGB是…

【51单片机】6-静态和动态控制数码管

1.什么是数码管 1.几方面看数码管 1. 外观 2.作用 数码管是显示器件&#xff0c;用来显示数字的 3.分类 单个&#xff08;1位&#xff09;&#xff0c;连排(2位&#xff0c;4位&#xff0c;8位&#xff09; 2.工作原理 1.亮灭原理 其实是内部的照明LED 2.显示数字 原理&…

速码!!BGP最全学习笔记:BGP概述

一、BGP概述 BGP是一种实现自治系统AS之间的路由可达&#xff0c;并选择最佳路由的矢量性协议。早期发布的三个版本分别是BGP-1&#xff08;RFC1105&#xff09;、BGP-2&#xff08;RFC1163&#xff09;和BGP-3&#xff08;RFC1267&#xff09;&#xff0c;1994年开始使用BGP-4…

【一人之下】杀了七个男童,只为修炼邪术!肖哥这一战可以封神!

Hello,小伙伴们&#xff0c;我是小郑继续为大家深度解析一人之下国漫。 在一人之下中&#xff0c;老肖是临时工里战力数一数二的存在&#xff0c;也是十佬之一解空大师的弟弟&#xff0c;平常看起来像一个热心肠的大哥&#xff0c;但却嗜好杀人&#xff0c;常挂在嘴边的一句话就…

基于微信小程序食谱大全系统设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言用户微信小程序端的主要功能有&#xff1a;管理员的主要功能有&#xff1a;具体实现截图详细视频演示为什么选择我自己的网站自己的小程序&#xff08;小蔡coding&#xff09;有保障的售后福利 代码参考论文参考源码获取 前言 &#x1f497;博主介绍&#xff1a;✌…

解决typescript报错=》不能将类型“undefined”分配给类型“boolean”

报错如下&#xff1a; 然后看看isSearch的类型定义&#xff1a; isSearch的定义是可选属性&#xff0c;但是TypeScript 中将一个参数标记为可选时&#xff0c;它的默认值将是 undefined。可选参数表示你可以选择性地提供该参数&#xff0c;如果不提供&#xff0c;那么它将默认为…

python随手小练1

题目&#xff1a; 使用python做一个简单的英雄联盟商城登录界面 具体操作&#xff1a; print("英雄联盟商城登录界面") print("~ * "*15 "~") #找其规律 a "1、用户登录" b "2、新用户注册" c "3、退出系统&quo…

实验室仪器应该如何清洗?

梵英超声(fanyingsonic)实验室超声波清洗机 实验室中常见的玻璃器皿如量杯、试管、滴定管、移液管、量瓶等等&#xff0c;是化学实验操作的核心组成部分。但这些玻璃器皿在使用过程中很容易沾上各种污渍&#xff0c;如油渍、血渍、水垢、锈渍等等&#xff0c;如果用完之后没有及…

xx-job凌晨一点清除oss指定文件夹以及指定保留时间的文件

ps&#xff1a;文件下面还有文件夹&#xff0c;这代码不能完全保证是否遍历到所有该文件夹以及子文件夹的文件&#xff0c;因为不可能一点点上到服务器去数&#xff0c;只是代码上做到应该不会出现重复的文件夹以及出现死循环 public static void main(String[] args) {long st…

在Idea中调试本地Docker

报错&#xff1a; Error running myApp: Unable to open debugger port (localhost:5005): java.net.SocketException "Connection reset" 原因&#xff1a; Docker配置里边没有配置环境变量JAVA_TOOL_OPTIONS. 解决&#xff1a; 在Docker下加入运行时的环境变量JAVA…

解决0-1背包问题(方案一):二维dp数组

>>确定dp数组以及下标的含义 dp[i][j]表示从下标为[0-i]的物品里任意取&#xff0c;放进容量为j的背包&#xff0c;价值总和最大是多少 &#xff08;1&#xff09;不放物品i 例如&#xff1a;当背包的容量是1kg&#xff0c;此时物品1和物品2都是无法放进去的。而物品0…

【前端】常用属性及实例

1. 盒子水平垂直居中 1&#xff09;flex布局实现水平垂直居中 <style>.box {background: yellow;width: 200px;height: 200px;/* 设置flex布局 */display: flex;/* 水平居中 */justify-content: center;/* 垂直居中 */align-items: center;}.col {margin: 1px;backgroun…

使用 queueMicrotask 创建微任务!

之前我们想尽一切办法来创建一个自定义的微任务&#xff0c;如 Promise.then、MutationObserver&#xff08;浏览器环境中的 API&#xff0c;用于监视 DOM 变动&#xff09;、async/await、process.nextTick&#xff08;仅Node.js支持&#xff0c;本质来说它不是事件循环的一部…