python coding with ChatGPT 打卡第20天| 二叉搜索树:搜索、验证、最小绝对差、众数

相关推荐
python coding with ChatGPT 打卡第12天| 二叉树:理论基础
python coding with ChatGPT 打卡第13天| 二叉树的深度优先遍历
python coding with ChatGPT 打卡第14天| 二叉树的广度优先遍历
python coding with ChatGPT 打卡第15天| 二叉树:翻转二叉树、对称二叉树
python coding with ChatGPT 打卡第16天| 二叉树:完全二叉树、平衡二叉树、二叉树的所有路径、左叶子之和
python coding with ChatGPT 打卡第17天| 二叉树:找树左下角的值、路径总和
python coding with ChatGPT 打卡第18天| 二叉树:从中序与后序遍历序列构造二叉树、最大二叉树
python coding with ChatGPT 打卡第19天| 二叉树:合并二叉树

二叉搜索树中的搜索

Key Points

1.二叉搜索树是一个有序树:

- 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
- 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
- 它的左、右子树也分别为二叉搜索树

2.二叉搜索树的迭代
一提到二叉树遍历的迭代法,可能立刻想起使用栈来模拟深度遍历,使用队列来模拟广度遍历。

对于二叉搜索树可就不一样了,因为二叉搜索树的特殊性,也就是节点的有序性,可以不使用辅助栈或者队列就可以写出迭代法

对于一般二叉树,递归过程中还有回溯的过程,例如走一个左方向的分支走到头了,那么要调头,在走右分支。

对于二叉搜索树,不需要回溯的过程,因为节点的有序性就帮我们确定了搜索的方向

相关题目

700. 二叉搜索树中的搜索

视频讲解

这次搜索有方向了

重点分析

方法一:
递归法

def searchBST(root, val):
    if not root:
        return None
    if root.val > val:
        return searchBST(root.left, val)
    if root.val < val:
        return searchBST(root.right, val)
    return root

方法二:
迭代法

def searchBST(root, val):
    current = root
    while current:
        if current.val > val:
                current = current.left
                continue
        if current.val < val:
                current = current.right
                continue
        else:
            break
    return current

验证二叉搜索树

Key Points

中序遍历下,输出的二叉搜索树节点的数值是升序序列。

相关题目

98. 验证二叉搜索树

视频讲解

你对二叉搜索树的了解还不够

重点分析

方法一:
不使用有序序列
在这里插入图片描述
我们可以定义一个辅助函数checkBST,它接收四个参数:当前节点node、minVal(当前节点值允许的最小值)、maxVal(当前节点值允许的最大值)、以及初始的根节点root。这个辅助函数将帮助我们递归地验证每个子树,同时保持跟踪允许的值的范围。

def checkBST(node, minVal, maxVal):
    if not node:
        return True
    if node.val <= minVal or node.val >= maxVal:
        return False
    return checkBST(node.left, minVal, node.val) and checkBST(node.right, node.val, maxVal)

def isValidBST(root):
    return checkBST(root, float('-inf'), float('inf'))

这段代码使用了一个嵌套的辅助函数checkBST来递归地验证每个节点是否符合二叉搜索树的条件,它通过维护每个节点的值允许的最小值和最大值来实现。这种方法能够确保所有的左子树节点都小于它的父节点,并且所有的右子树节点都大于它的父节点,同时还考虑了所有祖先节点的约束条件。

方法二:
使用有序序列 + 双指针 递归法
在这里插入图片描述

class Solution:
    def __init__(self):
        self.pre = None  # 用来记录前一个节点

    def isValidBST(self, root):
        if root is None:
            return True

        left = self.isValidBST(root.left)

        if self.pre is not None and self.pre.val >= root.val:
            return False
        self.pre = root  # 记录前一个节点

        right = self.isValidBST(root.right)
        return left and right

方法三:
使用有序序列 + 双指针 迭代法

在这里插入图片描述

def isValidBST(root):
    stack = []
    prev = None
    
    while stack or root:
        # 遍历到最左
        while root:
            stack.append(root)
            root = root.left
        
        # 访问节点
        root = stack.pop()
        
        # 检查当前节点是否大于前一个节点
        if prev and root.val <= prev.val:
            return False
        prev = root
        
        # 转向右子树
        root = root.right
    
    return True

二叉搜索树的最小绝对差

Key Points

  1. 在升序数组中,任意两个相邻元素的差值最小
  2. 1)暴力法:先中序遍历得到升序数列,再遍历数组求最小差值;
    2)简化法:遍历的过程中使用双指针

相关题目

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

视频讲解

二叉搜索树中的双指针遍历

重点分析

方法一:
递归法

class Solution(object):
    def __init__(self):
        self.pre = None   
        self.diff = float('inf')  # 只使用一次,所以是全局变量
        
    def getMinimumDifference(self, root):
        self.in_traversal(root)
        return self.diff

    def in_traversal(self, root):
        if not root:
            return
        self.in_traversal(root.left)
        if self.pre:
            self.diff = min(root.val - self.pre.val, self.diff)
        self.pre = root
        self.in_traversal(root.right)
        return

方法二:
迭代法 + 暴力

def getMinimumDifference(root):
    stack_record = []
    current = root
    res = []
    while stack_record or current:
        while current:
            stack_record.append(current)
            current = current.left

        current = stack_record.pop()
        res.append(current.val)

        # 左中都处理完了,转向右
        current = current.right

    i = 0
    j = i+1
    diff = res[j] - res[i]
    while j < len(res):
        diff = min(res[j] - res[i], diff)
        i += 1
        j += 1
    return diff

注:LeetCode题目中说明节点至少为两个,所以使用双指针不用讨论数组长度

方法三:
迭代法+简化

def getMinimumDifference(root):
    stack_record = []
    current = root
    diff = float('inf')
    pre = None
    while stack_record or current:
        while current:
            stack_record.append(current)
            current = current.left

        current = stack_record.pop()
        if pre is None:   # if not pre 不行,警惕0的情况
            pre = current.val
        else:
            diff = min(current.val-pre, diff)
            pre = current.val

        current = current.right

    return diff

二叉搜索树中的众数

Key Points

首先如果不是二叉搜索树的话,应该怎么解题,是二叉搜索树,又应该如何解题,两种方式做一个比较,可以加深大家对二叉树的理解。

  1. 如果不是二叉搜索树,最直观的方法一定是把这个树都遍历了,用map统计频率,把频率排个序,最后取前面高频的元素的集合。
  2. 对于二叉搜索树,遍历有序数组的元素出现频率,从头遍历,那么一定是相邻两个元素作比较,然后就把出现频率最高的元素输出就可以了。

相关题目

501. 二叉搜索树中的众数

视频讲解

双指针+代码技巧

重点分析

方法一:
暴力法 哈希表(迭代)

def findMode(root):
    res = []
    stack_record = []
    current = root

    while stack_record or current:
        while current:
            stack_record.append(current)
            current = current.left

        current = stack_record.pop()
        res.append(current.val)

        current = current.right

    record = {}
    for x in res:
        record[x] = record.get(x, 0) + 1

    record_sort = sorted(record.items(), key=lambda x:x[1], reverse=True)
    results = []
    max_val = record_sort[0][1]
    for x in record_sort:
        if x[1] == max_val:
            results.append(x[0])
        else:
            break

    return results

方法二:
遍历两遍 双指针 (迭代法)

def findMode(root):
    res = []
    stack_record = []
    current = root

    while stack_record or current:
        while current:
            stack_record.append(current)
            current = current.left

        current = stack_record.pop()
        res.append(current.val)

        current = current.right


    pre = None
    count = 0
    max_count = 0
    results = []

    for x in res:
        if pre is not None:
            if pre == x:
                count +=1
            else:
                count = 1
        else:
            count = 1
        pre = x
        if count == max_count:
            results.append(x)
        elif count > max_count:
            max_count = count
            results = [x]
    return results

方法三:
遍历一遍 迭代法

def findMode(root):
    res = []
    pre = None
    max_count = 0
    count = 0
    stack_record = []
    current = root

    while stack_record or current:
        while current:
            stack_record.append(current)
            current = current.left

        current = stack_record.pop()
        if pre:
            if current.val == pre.val:
                count += 1
            else:
                count = 1
        else:
            count = 1
        pre = current
        if count == max_count:
            res.append(current.val)
        elif count > max_count:
            max_count = count
            res = [current.val]

        current = current.right
    return res

方法四:
遍历一遍 递归法

class Solution:

    def __init__(self):
        self.pre = None
        self.res = []
        self.max_count = 0
        self.count = 0

    def in_traversal(self, root):
        if not root:
            return

        self.in_traversal(root.left)
        if self.pre:
            if root.val == self.pre.val:
                self.count += 1
            else:
                self.count = 1
        else:
            self.count = 1
        self.pre = root
        if self.count == self.max_count:
            self.res.append(root.val)
        elif self.count > self.max_count:
            self.max_count = self.count
            self.res = [root.val]

        self.in_traversal(root.right)
        return

    def findMode(self, root):
        self.in_traversal(root)
        return self.res

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

巧用Java 8中的 Function接口,消灭if.else!

点击上方“程序员蜗牛g”&#xff0c;选择“设为星标” 在开发过程中经常会使用if...else...进行判断抛出异常、分支处理等操作。这些if...else...充斥在代码中严重影响了代码代码的美观&#xff0c;这时我们可以利用Java 8的Function接口来消灭if...else...。 if (...){thro…

联想thinkpad-E450双系统升级记

早期笔记本联想thinkpad-E450双系统 大约16年花4000多大洋&#xff0c;买了一台thinkpad-E450屏幕是16寸本&#xff0c;有AMD独立显卡&#xff0c;i5cpu&#xff0c;4G内存。 . 后来加了一个同型号4G内存组成双通道&#xff0c; . 加了一个三星固态500G&#xff0c; . 换了一个…

【更新】企业数字化转型-年度报告175个词频、文本统计

数据说明&#xff1a; 这份数据含数字化转型175个词频、各维度水平&#xff0c;保留2000-2021年数据。参考吴非、赵宸宇两位老师做法&#xff0c;根据上市公司年报文本&#xff0c;整理数字化转型175个词频数据&#xff0c;希望对大家有所帮助。 参考管理世界中吴非&#xff…

车载电子电器架构 —— 电子电气系统控制器开发体系

车载电子电器架构 —— 电子电气系统控制器开发 我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 屏蔽力是信息过载时代一个人的特殊竞争力,任何消耗你的人和事,多看一眼都是你的不对。非必要不费…

【开源】SpringBoot框架开发APK检测管理系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 数据中心模块2.2 开放平台模块2.3 软件档案模块2.4 软件检测模块2.5 软件举报模块 三、系统设计3.1 用例设计3.2 数据库设计3.2.1 开放平台表3.2.2 软件档案表3.2.3 软件检测表3.2.4 软件举报表 四、系统展示五、核心代…

从互联网的公开信息中,找到属于你的赚钱思路

一、教程描述 人们在互联网上的每一次搜索、每一次关注、每一次点击、每一次点赞、每一次评论、每一次付费&#xff0c;都生成了大量的数据和信息&#xff0c;暴露着人们的真实想法、欲望、恐惧和需求。这些数据和信息&#xff0c;就是我们身边的一座“金矿”&#xff0c;而大…

读千脑智能笔记11_保存人类遗产

1. 智能生物通常能延续多久 1.1. SETI和METI计划的可行性在很大程度上取决于智能生物通常能延续多久 1.1.1. 搜寻地外文明&#xff08;以下简称SETI&#xff09;计划的目标 1.1.1.1. 这是一个力图寻找宇宙其他地方智能生物存在证据的研究项目 1.1.1.2. SETI计划旨在寻找含有…

基于Python的信息加密解密网站设计与实现【源码+论文+演示视频+包运行成功】

博主介绍&#xff1a;✌csdn特邀作者、博客专家、java领域优质创作者、博客之星&#xff0c;擅长Java、微信小程序、Python、Android等技术&#xff0c;专注于Java、Python等技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; …

【数学建模】【2024年】【第40届】【MCM/ICM】【E题 财产保险的可持续性】【解题思路】

一、题目 &#xff08;一&#xff09; 赛题原文 2024 ICM Problem E: Sustainability of Property Insurance Extreme-weather events are becoming a crisis for property owners and insurers. The world has endured “more than $1 trillion in damages from more than …

2024最新苹果电脑mac内存不够用?详细操作方法教程

你是否曾经在使用Mac时感到沮丧&#xff0c;因为那个彩色旋转球不停地在屏幕上转呢&#xff1f;那就是因为你的Mac正在大声呼救&#xff1a;“我的内存不够用了&#xff01;”不用担心&#xff0c;这里有一些绝妙的方法帮助Mac清理内存&#xff0c;让你的电脑恢复流畅运行&…

智慧地球(AI·Earth)社区AIO通用智能服务中心:一站式通用智能(AGI)服务体验

AIO通用智能服务中心 智慧地球&#xff08;AIEarth&#xff09;社区旨在搭建一个将人工智能&#xff08;AI&#xff09;变革性技术带给每个人的服务平台——AIO通用智能服务中心。我们的目标是提供一站式的AGI&#xff08;通用智能&#xff09;服务体验&#xff0c;持续开放最…

windows 查看磁盘空间 treesizefree

https://downloads.jam-software.de/treesize_free/TreeSizeFreeSetup.exe

DRF 分页器的使用

drf提供了三个内置分页器&#xff0c;根据前端需求选择使用。 全局配置 在配置文件中设置全局的分页方式&#xff0c;如&#xff1a; REST_FRAMEWORK {DEFAULT_PAGINATION_CLASS: rest_framework.pagination.PageNumberPagination,PAGE_SIZE: 100 # 每页数目 }也可通过继…

从零开始实现消息队列(二)

从零开始实现消息队列 .核心API交换机类型持久化网络通信Connection和Channel 消息应答模块划分 . 核心API 对于Broker来说,要实现以下核心API,通过这些API来实现消息队列的基本功能. 创建队列(queueDeclare)销毁队列(queueDelete)创建交换机(exchangeDeclare)销毁交换机(exc…

《UE5_C++多人TPS完整教程》学习笔记5 ——《P6 在线子系统(Online Subsystem)》

本文为B站系列教学视频 《UE5_C多人TPS完整教程》 —— 《P6 在线子系统&#xff08;Online Subsystem&#xff09;》 的学习笔记&#xff0c;该系列教学视频为 Udemy 课程 《Unreal Engine 5 C Multiplayer Shooter》 的中文字幕翻译版&#xff0c;UP主&#xff08;也是译者&a…

13. 【Linux教程】移动文件和目录

移动文件和目录 前面小节介绍了如何创建文件和目录、删除文件和目录&#xff0c;本小节介绍如何使用 mv 命令移动文件和目录。 1. 移动文件或目录至另外一个目录下 可以使用 mv file_name 路径 这种格式&#xff0c;移动文件至其他目录下&#xff0c;后面跟的路径可以是相对路…

Unity学习笔记(零基础到就业)|Chapter04:C#篇补充到Unity篇过渡

Unity学习笔记&#xff08;零基础到就业&#xff09;&#xff5c;Chapter02:C#篇补充到Unity篇过渡 前言C#总结补充1.值类型和引用类型有什么区别&#xff0c;他们在值的传递上分别有怎样的特性2.string是引用类型&#xff0c;但是他对外表现出值类型的特性&#xff0c;为什么&…

第4集《佛说四十二章经》

请大家打开讲议第四面&#xff0c;第一章&#xff0c;出家证果。 佛言&#xff1a;辞亲出家&#xff0c;识心达本&#xff0c;解无为法&#xff0c;名曰沙门。 在经文的刚开始啊&#xff0c;佛陀把修道的沙门提出了两个基本的条件&#xff1a; 第一个是辞亲出家&#xff0c;…

口腔助手|口腔挂号预约小程序|基于微信小程序的口腔门诊预约系统的设计与实现(源码+数据库+文档)

口腔小程序目录 目录 基于微信小程序的口腔门诊预约系统的设计与实现 一、前言 二、系统功能设计 三、系统实现 1、小程序前台界面实现 2、后台管理员模块实现 四、数据库设计 1、实体ER图 2、具体的表设计如下所示&#xff1a; 五、核心代码 六、论文参考 七、最新…

sheng的学习笔记-docker部署数据库oracle,mysql

部署目录&#xff1a;sheng的学习笔记-部署-目录-CSDN博客 docker基础知识可参考 sheng的学习笔记-docker部署&#xff0c;原理图&#xff0c;命令&#xff0c;用idea设置docker docker安装数据库 mac版本 安装oracle 下载oracle镜像 打开终端&#xff0c;输入 docker s…