Python蓝桥杯训练:基本数据结构 [二叉树] 上

news2024/10/2 22:30:10

Python蓝桥杯训练:基本数据结构 [二叉树] 上

文章目录

  • Python蓝桥杯训练:基本数据结构 [二叉树] 上
    • 一、前言
    • 二、有关二叉树理论基础
      • 1、二叉树的基本定义
      • 2、二叉树的常见类型
      • 3、二叉树的遍历方式
    • 三、有关二叉树的层序遍历的题目
      • 1、[二叉树的层序遍历](https://leetcode.cn/problems/binary-tree-level-order-traversal/)
      • 2、[N叉树的层序遍历](https://leetcode.cn/problems/n-ary-tree-level-order-traversal/)
      • 3、填充每个节点的下一个右侧节点指针

一、前言

目前蓝桥杯训练刷题刷到了二叉树,中间的栈和队列我没有更新,时间有点不太够,但是我又觉得如果刷题不写笔记的话感觉等于没刷,所以我还是将我刷题的过程以笔记的形式总结出来,内容可能没有之前几次的丰富但是我还是会将重要的内容总结出来,理论部分会有所减少,我会更加专注 于总结刷题过程中的思考。

二、有关二叉树理论基础

二叉树是一种树状数据结构,它的每个节点最多只有两个子节点。其中一个被称为左子节点,另一个被称为右子节点。以下是有关二叉树的理论基础的详细总结:

1、二叉树的基本定义

  • 节点(Node):二叉树的基本单位,它包含一个值(Value)和两个指针(Pointer),分别指向左子节点和右子节点(如果没有子节点,则指向 null 或空)。
  • 根节点(Root):二叉树中的第一个节点,它没有父节点,是整棵树的起点。
  • 叶节点(Leaf):没有子节点的节点称为叶节点。
  • 内部节点(Internal Node):除了叶节点以外的节点都称为内部节点。
  • 高度(Height):二叉树的高度是从根节点到最深叶节点的最长路径的长度。空树的高度为0,只有一个节点的二叉树的高度为1。
  • 深度(Depth):节点的深度是从根节点到该节点的唯一路径的长度。根节点的深度为0。
  • 路径(Path):是指从一个节点到另一个节点经过的所有节点的序列。
  • 子树(Subtree):是指由一个节点及其所有后代节点组成的二叉树。

2、二叉树的常见类型

  • 普通二叉树(Binary Tree):每个节点最多只有两个子节点。
  • 完全二叉树(Complete Binary Tree):除了最后一层,每一层的节点数都是满的,并且最后一层的节点都尽可能地靠左。
  • 满二叉树(Full Binary Tree):每个节点都有 0 或 2 个子节点,没有只有一个子节点的节点。
  • 二叉搜索树(Binary Search Tree):每个节点的左子树中的所有节点的值都小于该节点的值,右子树中的所有节点的值都大于该节点的值。
  • 平衡二叉树(Balanced Binary Tree):左右子树的高度差不超过 1 的二叉树。

3、二叉树的遍历方式

二叉树的深度优先遍历方式有三种:前序遍历、中序遍历和后序遍历,广度优先遍历有层序遍历。这些遍历方式都是基于递归的,它们都可以使用递归或迭代法来实现。

  • 深度优先遍历

    • 前序遍历:先访问根节点,再递归地访问左子树和右子树。

      class Node:
          def __init__(self, value):
              self.left = None
              self.right = None
              self.value = value
      
      def preorder_traversal(node):
          if node is None:
              return
          print(node.value)
          preorder_traversal(node.left)
          preorder_traversal(node.right)
      
      root = Node(1)
      root.left = Node(2)
      root.right = Node(3)
      root.left.left = Node(4)
      root.left.right = Node(5)
      
      print("前序遍历结果:")
      preorder_traversal(root)
      
      前序遍历结果:
      1
      2
      4
      5
      3
      
    • 中序遍历:先递归地访问左子树,再访问根节点,最后递归地访问右子树。

      class Node:
          def __init__(self, value):
              self.left = None
              self.right = None
              self.value = value
      
      def inorder_traversal(node):
          if node is None:
              return
          inorder_traversal(node.left)
          print(node.value)
          inorder_traversal(node.right)
      
      root = Node(1)
      root.left = Node(2)
      root.right = Node(3)
      root.left.left = Node(4)
      root.left.right = Node(5)
      
      print("中序遍历结果:")
      inorder_traversal(root)
      
      中序遍历结果:
      4
      2
      5
      1
      3
      
    • 后序遍历:先递归地访问左子树和右子树,最后访问根节点。

      class Node:
          def __init__(self, value):
              self.left = None
              self.right = None
              self.value = value
      
      def postorder_traversal(node):
          if node is None:
              return
          postorder_traversal(node.left)
          postorder_traversal(node.right)
          print(node.value)
      
      root = Node(1)
      root.left = Node(2)
      root.right = Node(3)
      root.left.left = Node(4)
      root.left.right = Node(5)
      
      print("后序遍历结果:")
      postorder_traversal(root)
      
      后序遍历结果:
      4
      5
      2
      3
      1
      
  • 广度优先遍历

    也称作层序遍历,是按照层次顺序从上往下、从左往右遍历树的节点。广度优先遍历需要借助队列来实现,每次从队列中取出一个节点,访问它的左右子节点,将子节点依次加入队列中,直到队列为空。

    from collections import deque
    
    class Node:
        def __init__(self, value):
            self.left = None
            self.right = None
            self.value = value
    
    def breadth_first_traversal(node):
        if node is None:
            return
        queue = deque()
        queue.append(node)
        while queue:
            current_node = queue.popleft()
            print(current_node.value)
            if current_node.left:
                queue.append(current_node.left)
            if current_node.right:
                queue.append(current_node.right)
    
    root = Node(1)
    root.left = Node(2)
    root.right = Node(3)
    root.left.left = Node(4)
    root.left.right = Node(5)
    
    print("广度优先遍历结果:")
    breadth_first_traversal(root)
    
    广度优先遍历结果:
    1
    2
    3
    4
    5
    

三、有关二叉树的层序遍历的题目

二叉树的层序遍历相比于其深度优先遍历会简单很多,基本记住一个模板很多题目就可以直接套用。

1、二叉树的层序遍历

给你二叉树的根节点 root ,返回其节点值的 层序遍历 。 (即逐层地,从左到右访问所有节点)。

示例 1:

在这里插入图片描述

输入:root = [3,9,20,null,null,15,7]
输出:[[3],[9,20],[15,7]]

示例 2:

输入:root = [1]
输出:[[1]]

示例 3:

输入:root = []
输出:[]

提示:

  • 树中节点数目在范围 [0, 2000] 内

  • -1000 <= Node.val <= 1000

这道题就是考察我们对二叉树层序遍历的掌握情况,在上面的二叉树理论基础中的广度优先遍历中我们已经实现了这个过程,并且使用的迭代方法,下面我来说一下递归的方法如何实现。

实现思路跟迭代法一样就是代码更加简洁,具体思路我写在了代码注释里面。

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution():
    def levelOrder(self, root: TreeNode) -> List[List[int]]:
        result = []  # 定义一个列表,用于保存最终结果

        def traverse(node, level):
            if not node:  # 如果当前节点为空,直接返回
                return
            if level == len(result):  # 如果 result 中不存在当前层的列表,创建一个新的列表
                result.append([])
            result[level].append(node.val)  # 将当前节点的值加入当前层的列表中
            traverse(node.left, level + 1)  # 6递归遍历当前节点的左子树
            traverse(node.right, level + 1)  # 7. 递归遍历当前节点的右子树

        traverse(root, 0)  # 开始遍历二叉树
        return result  # 返回最终结果

2、N叉树的层序遍历

给定一个 N 叉树,返回其节点值的层序遍历。(即从左到右,逐层遍历)。

树的序列化输入是用层序遍历,每组子节点都由 null 值分隔(参见示例)。

示例 1:
在这里插入图片描述

输入:root = [1,null,3,2,4,null,5,6]
输出:[[1],[3,2,4],[5,6]]

示例 2:

在这里插入图片描述

输入:root = [1,null,2,3,4,5,null,null,6,7,null,8,null,9,10,null,null,11,null,12,null,13,null,null,14]
输出:[[1],[2,3,4,5],[6,7,8,9,10],[11,12,13],[14]]

提示:

  • 树的高度不会超过 1000
  • 树的节点总数在 [0, 10^4] 之间

这道题目也是套模板,只不过在左孩子和右孩子的基础上多了一个孩子。

"""
# Definition for a Node.
class Node:
    def __init__(self, val=None, children=None):
        self.val = val
        self.children = children
"""
# 迭代法
class Solution:
    def levelOrder(self, root: 'Node') -> List[List[int]]:
        if not root:
            return []
        res = []
        queue = [root]
        while queue:
            level = []
            size = len(queue)
            for i in range(size):
                node = queue.pop(0)
                level.append(node.val)
                for child in node.children:
                    queue.append(child)
            res.append(level)
        return res

递归法实现就是从根节点开始,递归遍历每一层的节点,并将它们添加到对应层的列表中。

class Solution:
    def levelOrder(self, root: 'Node') -> List[List[int]]:
        if not root:  # 如果根节点为空,则直接返回空列表
            return []
        res = []  # 存储结果的列表
        def traverse(node, level):
            # 如果当前层数等于列表长度,则向列表中添加一个新列表
            if len(res) == level:
                res.append([])
            # 将当前节点的值加入到对应层的列表中
            res[level].append(node.val)
            # 递归遍历当前节点的所有子节点,并将它们的层数加一,作为递归函数的参数进行递归
            for child in node.children:
                traverse(child, level+1)
        # 从根节点开始递归遍历
        traverse(root, 0)
        return res  # 返回结果列表

3、填充每个节点的下一个右侧节点指针

给定一个 完美二叉树 ,其所有叶子节点都在同一层,每个父节点都有两个子节点。二叉树定义如下:

struct Node {
  int val;
  Node *left;
  Node *right;
  Node *next;
}

填充它的每个 next 指针,让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点,则将 next 指针设置为 NULL。

初始状态下,所有 next 指针都被设置为 NULL。

示例 1:

在这里插入图片描述

输入:root = [1,2,3,4,5,6,7]
输出:[1,#,2,3,#,4,5,6,7,#]
解释:给定二叉树如图 A 所示,你的函数应该填充它的每个 next 指针,以指向其下一个右侧节点,如图 B 所示。序列化的输出按层序遍历排列,同一层节点由 next 指针连接,'#' 标志着每一层的结束。

示例 2:

输入:root = []
输出:[]

提示:

  • 树中节点的数量在 [0, 212 - 1] 范围内
  • -1000 <= node.val <= 1000

进阶:

  • 你只能使用常量级额外空间。
  • 使用递归解题也符合要求,本题中递归程序占用的栈空间不算做额外的空间复杂度。

这道题目的要求就是给定一棵二叉树,将每个节点的右子节点指向其在右边的下一个节点,如果右边没有节点,则将其指向None。要求使用常数级额外空间,也就是说不可以使用队列等数据结构。

题目要求在不使用队列等数据结构的情况下,将每个节点的右子节点指向其在右边的下一个节点。

我们可以从根节点开始,对于每一层节点,依次更新它们的右子节点,直到该层节点的最后一个节点。然后再进入下一层节点进行同样的操作。

具体来说我们指定一个指针 cur,表示当前层节点的最左边的节点,初始时 cur 指向根节点。在每一层的循环中,我们从左到右遍历该层的所有节点,对于每个节点,先将其左子节点的 next 指针指向其右子节点,再将其右子节点的 next 指针指向其 next 指针所指向节点的左子节点(如果该节点的 next 指针所指向节点不存在,则将其右子节点的 next 指针指向 None)。然后将该节点移动到下一个节点,直到该层的所有节点都被更新为止。最后将 cur 指针移动到下一层的最左边的节点,并重复上述操作,直到遍历完所有层为止。

"""
# Definition for a Node.
class Node:
    def __init__(self, val: int = 0, left: 'Node' = None, right: 'Node' = None, next: 'Node' = None):
        self.val = val
        self.left = left
        self.right = right
        self.next = next
"""

class Solution:
    def connect(self, root: 'Node') -> 'Node':
        if not root:
            return None
        cur = root
        while cur.left:
            node = cur
            while node:
                node.left.next = node.right
                if node.next:
                    node.right.next = node.next.left
                node = node.next
            cur = cur.left
        return root

时间复杂度: O ( n ) O(n) O(n),其中 n n n 是二叉树中的节点个数。

空间复杂度: O ( 1 ) O(1) O(1)。除了存储答案所需的空间外,我们只需要维护常数个变量,因此空间复杂度是 O ( 1 ) O(1) O(1)

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

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

相关文章

网络原理之传输层协议,TCP中的主要核心机制(重点)

目录 一. 传输层中的端口号 二. UDP协议 三. TCP协议 四. TCP中的核心机制 1. 确认应答 2. 超时重传 3. 连接管理 建立连接(三次握手) 断开连接(四次挥手) 4. 滑动窗口 考虑丢包情况1&#xff1a;ack丢了 考虑丢包情况2&#xff1a;数据丢了 5. 流量控制 6. 拥塞…

学这些语言工作更吃香,Python虽然再次摘得桂冠,但在就业需求中位居第一的还得是它!

2022 IEEE 编程语言榜单发布&#xff01; IEEE Spectrum 2022 编程语言排名前十的分别是&#xff1a;Python&#xff0c;C&#xff0c;C&#xff0c;C#&#xff0c;Java&#xff0c;SQL&#xff0c;JavaScript&#xff0c;R&#xff0c;HTML&#xff0c;TypeScript。 一. Pyth…

嵌入式学习笔记——寄存器实现控制LED小灯

文章目录前言GPIO通用输出模式初始化LED小灯的GPIO原理图初始化代码初始化的效果功能函数封装直接分开宏定义两个使用条件运算符封装函数实现简单的功能前言 上一篇中&#xff0c;介绍了GPIO相关的所有寄存器&#xff0c;并在最后简单实现了一个LED灯的控制&#xff0c;由于那…

以获取笔记本电池信息为例介绍WMI的使用

注&#xff1a;本人也还没有完全弄懂WMI的原理&#xff0c;以下内容仅供参考。。。 简单来说&#xff0c;比起Win32提供的接口&#xff0c;WMI可以提供更多的系统信息&#xff0c;它本身是一个数据库架构&#xff0c;通过它可以访问、配置、管理和监视几乎所有的Windows资源&…

AM5728(AM5708)开发实战之移植OpenCV-3.4.11

一 概述 OpenCV是一个开源的跨平台计算机视觉库&#xff0c;可以运行在Linux、Windows、Mac OS等操作系统上&#xff0c;它为图像处理、模式识别、三维重建、物体跟踪、机器学习提供了丰富的算法。 由于OpenCV依赖包特别多&#xff0c;尽量不要使用交叉编译&#xff0c;即在什…

VMware虚拟机搭建环境通用方法

目录一、前期准备1.下载并安装一个虚拟机软件二、开始创建虚拟机1.配置虚拟机硬件相关操作2.虚拟机网络相关操作三、开机配置相关内容0.开机遇到报错处理&#xff08;选看--开机没有报错请忽略&#xff09;1.开始配置2.开机之后配置3.使用xshell远程登录4.使用xshell配置虚拟机…

下一个7年,保持期待、持续思考,酷雷曼继续向前!

过去7年&#xff0c;我们一直在思考&#xff0c; VR技术究竟能为我们的生活带来什么&#xff1f; 是足不出户就能云游千里的秀美风光&#xff1f; 是在家就能沉浸式体验线上消费的便利&#xff1f; 还是为商企和用户搭建更快速的沟通桥梁&#xff1f; NO.1、技术变革 在信…

磁盘阵列Raid探讨

最近公司买服务器&#xff0c;顺便了解一下服务器配置方面的问题 以下讨论的都是入门级服务器配置&#xff0c;全部是主观意见&#xff0c;没有任何科学依据&#xff0c;欢迎大家讨论 Raid0&#xff0c;Raid1&#xff0c;Raid10&#xff0c;Raid5&#xff0c;Raid6(Raid5热备)…

计算机科学导论笔记(四)

目录 六、计算机网络和因特网 6.1 引言 6.1.1 网络 6.1.2 因特网 6.1.3 硬件和软件 6.1.4 协议分层 6.1.5 TCP/IP协议族 6.2 应用层 6.2.1 应用层模式 6.2.2 标准客户机-服务器应用 6.2.3 文件传输协议&#xff08;FTP&#xff09; 6.2.4 电子邮件 6.2.5 TELNET 6…

vue 模拟 chatgpt 聊天效果:js 实现逐字显示、延时函数模拟对话

vue 模拟 chatgpt 聊天效果&#xff1a;js 实现逐字显示、延时函数模拟对话模拟 chatgpt 聊天功能&#xff0c;展示对话效果。其中比较有意义的技术点是&#xff1a;js 实现逐字显示、延时函数&#xff0c;同步遍历。 <template><div class"chat-gpt">…

SpringBoot中的bean注入方式和原理介绍

Spring Boot是一个非常流行的Java框架&#xff0c;它可以帮助开发者快速地构建高效、健壮的应用程序。其中一个重要的功能就是依赖注入&#xff0c;也就是将一个对象注入到另一个对象中&#xff0c;以便它们可以相互协作。在Spring Boot中&#xff0c;依赖注入是通过bean实现的…

易优cms 标签常用函数

【基础用法】 标签&#xff1a;无 描述&#xff1a;作用于标签变量 用法&#xff1a; {$field.typename|html_msubstr###,0,10,true} 注意&#xff1a;函数与字段名之间用竖线&#xff08;|&#xff09;隔开&#xff0c;###表示当前变量 属性&#xff1a; 无 涉及表字段…

Kafka 消费进度

Kafka 消费进度Kafka 自带命令Java Consumer APIJMX 监控指标监控消费进度 : 看滞后程度&#xff1a;消费者 Lag , Consumer Lag 滞后程度 : 消费者落后于生产者的程度 如 : Kafka 生产者向某主题成功生产 100 万条消息&#xff0c;消费者消费 80 万条消息那消费者就滞后 20 …

ccc-pytorch-卷积神经网络实战(6)

文章目录一、CIFAR10 与 lenet5二、CIFAR10 与 ResNet一、CIFAR10 与 lenet5 第一步&#xff1a;准备数据集 lenet5.py import torch from torch.utils.data import DataLoader from torchvision import datasets from torchvision import transformsdef main():batchsz 128C…

基于嵌入式libxml2的ARM64平台的移植(aarch64)

由于libxml在移植过程中依赖于zlib的库文件&#xff0c;因此本节内容包含zlib&#xff08;V1.2.13&#xff09;的移植libxml2(V2.10.3)的移植两部分组成。 &#xff08;一&#xff09;zlib的移植&#xff08;基于arm64&#xff09; 1、在github上下载zlib的最新源码压缩包&am…

【C++的OpenCV】第十课-OpenCV图像常用操作(七):直方图和直方图同等化(直方图均衡化)

&#x1f389;&#x1f389;&#x1f389;欢迎各位来到小白piao的学习空间&#xff01;\color{red}{欢迎各位来到小白piao的学习空间&#xff01;}欢迎各位来到小白piao的学习空间&#xff01;&#x1f389;&#x1f389;&#x1f389; &#x1f496;&#x1f496;&#x1f496…

看完书上的链表还不会实现?不进来看看?

1.1链表的概念定义&#xff1a;链表是一种物理存储上非连续&#xff0c;数据元素的逻辑顺序通过链表中的指针链接次序&#xff0c;实现的一种线性存储结构。特点&#xff1a;链表由一系列节点组成&#xff0c;节点在运行时动态生成 &#xff08;malloc&#xff09;&#xff0c;…

【react】类组件

React类创建组件&#xff0c;通过继承React内置的Component来实现的 class MyComponent extends React.Component{render() {console.log(this)// render是放在哪里的 —— 类(即&#xff1a;MyComponent)的原型对象上&#xff0c;供实例使用return <h2>我是用函数定义的…

python实现波士顿房价预测

波士顿房价预测 目标 这是一个经典的机器学习回归场景&#xff0c;我们利用Python和numpy来实现神经网络。该数据集统计了房价受到13个特征因素的影响&#xff0c;如图1所示。 对于预测问题&#xff0c;可以根据预测输出的类型是连续的实数值&#xff0c;还是离散值&#xff…

QGraphicsItem的简单自定义图形项

QGraphicsItem的继承重写序言重点函数QRectF boundingRect() constQPainterPath shape() constvoid paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget 0)序言 学习途中记录一下&#xff0c;可谓是精华点 重点函数 QRectF boundingRect()…