代码随想录Day22:二叉树Part8

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

讲解前:

这道题其实可以用完全一样的code和普通二叉树的公共祖先一样,得到答案,但是那样就完全没有用到BST的特性,我这里的解法其实也不知道是不是用到了BST的特性,我这里觉得既然是二叉搜索树就证明左右子树的整体是比root大或者小的,所以其实在每一个root的时候,如果p和q都同时比root大或者比root小,那么我们就没必要对另外一边的子树进行递归,因为公共祖先肯定不可能在那边,因为那边可能包含p和q的node,所以就只对一边进行递归然后另一边直接设成none

然后呢还有另外一种情况,当我们发现p和q分别一个大于当前root一个小于当前root的时候,我们就可以直接返回root了,因为在二叉搜索树中,这种情况发生的时候,p和q一定分别在我们树的左右两个子树中,意味着他们不可能再有机会有相同的公共祖先了出了当前节点以外

class Solution:
    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
        
        # base case
        # when we get to the none node or we found either p or q
        if not root:
            return None
        elif root is q or root is p:
            return root
        
        # recursive case
        # since is BST, we can choose whether is need to 
        # traverse 
        # when p an q both exist in the left sub tree
        if p.val < root.val and q.val < root.val:
            left = self.lowestCommonAncestor(root.left, p, q)
            right = None
        elif p.val > root.val and q.val > root.val:
            left = None
            right = self.lowestCommonAncestor(root.right, p, q)
        elif p.val < root.val and q.val > root.val:
            return root
        elif p.val > root.val and q.val < root.val:
            return root

        
        # check what to return
        if left and not right:
            return left
        elif right and not left:
            return right
        else:
            return None
讲解后:

看完了卡哥的解法之后发现卡哥的思路和我是一样的但是代码更加简洁了,因为我们能够直接通过如果pq在树的左右就直接判断是不是最近公共祖先,那就可以直接return root,所以这里其实代码可以简洁很多

class Solution:
    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
        
        # base case
        # when we get to the none node or we found either p or q
        if not root:
            return None
        
        # recursive case
        # since is BST, we can choose whether is need to 
        # traverse 
        # when p an q both exist in the left sub tree
        if p.val < root.val and q.val < root.val:
            left = self.lowestCommonAncestor(root.left, p, q)
            if left:
                return left
        elif p.val > root.val and q.val > root.val:
            right = self.lowestCommonAncestor(root.right, p, q)
            if right:
                return right
        else:
            return root

也就是说这里我们的base case只需要当遍历到空节点的时候就返回none,然后呢在遍历的时候,需要先确定如果pq在同一边,那么我们就需要进行递归,并且其实如果递归之后发现左边的递归或者右边的递归找到了答案,就直接return 那个答案就行了,如果并不是pq都在同一边,就直接return root就行了

然后呢就是迭代法

class Solution:
    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
        
        while root:

            if root.val == p.val or root.val == q.val:
                return root
            elif (p.val < root.val and q.val > root.val) or (q.val < root.val and p.val > root.val):
                return root

            elif p.val < root.val and q.val < root.val:
                root = root.left
            else:
                root = root.right

其实就是当root不为空的时候,我们就在while循环中遍历,然后呢当我们发现root已经变成了p或者q的其中一个的时候,就可以直接return root了,然后呢如果p和q分别在左右子树之中,就直接return当前的根节点,不是这种情况的话,就根据pq都大或者都小来左右遍历


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

讲解前:

我的这个解法其实有一点点不完美,edge case还需要在最后处理,总体思想其实也很简单,我们其实就是通过递归然后直到我们为val找到了一个位置,然后就把val加入到那个root相应的左右节点,这就是base case,然后呢左右递归的时候,只需要注意要遵循二叉搜索树的条件就可以了,就是val如果比root小就往左遍历,大就往右遍历

class Solution:
    def insertIntoBST(self, root: Optional[TreeNode], val: int) -> Optional[TreeNode]:

        def dfs(root, val):
            # base case is when we found a empty spot
            if not root.left and val < root.val:
                root.left = TreeNode(val)
                return 
            elif not root.right and val > root.val:
                root.right = TreeNode(val)
                return
            
            # recursive case to keep going 
            if root.left and val < root.val:
                dfs(root.left, val)
            elif root.right and val > root.val:
                dfs(root.right, val)
        
        if not root:
            return TreeNode(val)
        else:
            dfs(root, val) 
            return root
讲解后:

卡哥对于这道题的解法是通过在base case那里遍历到空节点之后呢,创建一个val 的节点然后呢返回,所以当我们在递归的时候对每一个节点就直接让他的left或者right指向递归的函数,但是我觉得这种方法还是有一点点不好理解对于其他root是怎么一层一层返回上去的,我的解法属于直接赋值然后return结束递归的方法

Leetcode 450. 删除二叉树

讲解前:

这道题还是很有难度的,有非常多的细节需要考虑,我觉得如果直接自己尝试去做的话可能会花费很多的时间debug所以我打算直接看视频来做

讲解后:

看完了卡哥的讲解之后思路就变得非常清晰了,这道题其实就是一开始的思路就要搞对,也就是我们总体的思路是在base case的时候就对节点进行删除,所以我们base case进去之前要比较root.val == key,其次删除的方法是利用返回节点的方式,设想成就像链表一样,我们删除的时候是用被删除的节点的父节点然后指向删除节点的子节点,把删除的节点跳过的操作,所以在base case的处理中我们用的是return root.left 或者 return root.right的操作,然后呢在递归的时候就如果需要向左遍历,就root.left = deleteNode(root.left) 

唯一比较难的就是第五种可能,就是要删除的节点左右都有节点的情况,就如我下图中画的一样

这里我们要把14删除,意味着比14小的10为根的子树需要找一个新的父节点,那么应该找什么呢,其实就是出了14以外当时再大一点的节点,就可以当父节点了,那么就是16,因为16在14的右子树中,代表他比他大,16同时又是14右子树中最左边的节点,意味着他是14右子树中最小的那一个,所以我们就让16的左节点指向10(这里箭头朝向我画错了),然后呢再让3的右节点直接指向20就可以了

class Solution:
    def deleteNode(self, root: Optional[TreeNode], key: int) -> Optional[TreeNode]:

        # base case when we found the node 
        # case 1: we couldn't find the node
        if not root:
            return None
        
        if root.val == key:
        # case 2: the node is a leaf node
        # delete the node by return None to its parent
            if not root.left and not root.right:
                return None
        
        # case 3: the node only has left child 
            elif root.left and not root.right:
                return root.left
        
        # case 4: the node only has right child
            elif not root.left and root.right:
                return root.right
            
        # case 5: it has both child
            else:
                cur = root.right
                while cur.left:
                    cur = cur.left
                
                cur.left = root.left
                return root.right
        
        if key < root.val: root.left = self.deleteNode(root.left, key)
        if key > root.val: root.right = self.deleteNode(root.right, key)
        
        return root

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

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

相关文章

linux离线安装jenkins及使用教程

本教程采用jenkins.war的方式离线安装部署&#xff0c;在线下载的方式会遇到诸多问题&#xff0c;不宜采用 一、下载地址 地址&#xff1a;Jenkins download and deployment 下载最新的长期支持版 由于jenkins使用java开发的&#xff0c;所以需要安装的linux服务器装有jdk环…

【ESP32S3 Sense接入语音识别+MiniMax模型对话】

1. 前言 围绕ESP32S3 Sense接入语音识别MiniMax模型对话展开&#xff0c;首先串口输入“1”字符&#xff0c;随后麦克风采集2s声音数据&#xff0c;对接百度在线语音识别&#xff0c;将返回文本结果丢入MiniMax模型&#xff0c;进而返回第二次结果文本&#xff0c;实现语言对话…

【测试开发学习历程】Python数据类型:字符串-str(上)

目录 1 Python中的引号 2 字符串的声明 3 字符串的切片 4 字符串的常用函数 4.1 len()函数 4.2 ord()函数 4.3 chr()函数 5 字符串的常用方法&#xff08;内置方法/内建方法&#xff09; 5.1 find()方法 5.2 index()方法 5.3 rfind()方法 5.4 rindex()方法 1 Python…

每日一练:LeeCode-48、旋转图像【二维数组+行列交换】

给定一个 n n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。 你必须在原地 旋转图像&#xff0c;这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像。 示例 1&#xff1a; 输入&#xff1a;matrix [[1,2,3],[4,5,6],[7,8,9]] 输出…

免费软件“蓝莓投屏”:支持多个Airplay同时镜像的投屏软件。

引言&#xff1a; 由于定制盒子(3288)不支持投屏功能&#xff08;有些5.1不支持&#xff0c;安卓4.X本身也不支持&#xff09;&#xff0c;需要借助第三方的投屏软件来实现这一需求。所以&#xff0c;研究半天&#xff0c;蓝莓投屏以其简便易用的特性脱颖而出&#xff0c;只需…

imbalanced-learn,一个强大的 Python 库!

更多Python学习内容&#xff1a;ipengtao.com 大家好&#xff0c;今天为大家分享一个强大的 Python 库 - imbalanced-learn Github地址&#xff1a;https://github.com/scikit-learn-contrib/imbalanced-learn 在实际的数据分析和机器学习任务中&#xff0c;经常会遇到数据不平…

植物大战僵尸Javascript版web游戏源码

源码介绍 植物大战僵尸Javascript版web游戏源码&#xff0c;非常强大&#xff0c;1比1还原电脑版植物大战僵尸游戏&#xff0c;带背景音乐&#xff0c;玩法和原版一模一样。 源码截图 下载地址 https://download.csdn.net/download/huayula/89048275

基于微信小程序的民宿短租系统设计与实现(论文+源码)_kaic

摘 要 随着社会的发展&#xff0c;出差、旅游成为常态&#xff0c;也就造成民宿短租市场的兴起。人们新到陌生的环境里找民宿一般都是通过中介。中介虽然可以快速找到合适的民宿但会收取大量的中介费用&#xff0c;这对刚到新环境里的人们来说是一笔大的资金支出。也有一些人通…

Linux内核之最核心数据结构之二:struct inode(三十一)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…

k8s局域网通过operator部署rabbitmq

参考&#xff1a;Installing RabbitMQ Cluster Operator in a Kubernetes Cluster | RabbitMQ 1、下载cluster-operator.yml wget https://github.com/rabbitmq/cluster-operator/releases/download/v2.7.0/cluster-operator.yml 2、拉取对应的镜像&#xff0c;这里的版本是根…

springboot+vue在idea上面的使用小结

1.在mac上面删除java的jdk方法&#xff1a; sudo rm -rfjdk的路径 sudo rm -rf /Users/like/Library/Java/JavaVirtualMachines/corretto-17.0.10/Contents/Home 2.查询 Mac的jdk版本和路径&#xff1a; /usr/libexec/java_home -V 3.mac上面查询和关闭idea的网页端口&…

|行业洞察·汽车|《新能源汽车行业发展及营销策略分析-35页》

报告的主要内容解读&#xff1a; 行业环境&#xff1a;报告指出&#xff0c;海外车企的电动化进程遇到阻碍&#xff0c;而中国新能源汽车市场持续增长&#xff0c;2023年销量占全球新能源汽车的63.5%&#xff0c;市占率达到31.6%。 市场政策&#xff1a;中国政府通过减免税收、…

GT收发器第一篇_总体结构介绍

文章目录 前言GT收发器介绍 前言 之前写过一篇简单介绍GT的文章https://blog.csdn.net/m0_56222647/article/details/136730026&#xff0c;可以先通过这篇文章对整体进行简单了解一下。 GT收发器介绍 参考xilinx手册ug476 对于7系列的FPGA&#xff0c;共有3个系列&#xf…

JAVAEE——线程池

文章目录 线程池的概念什么是线程池&#xff1f; 标准库中的线程池线程池的创建工厂模式工厂模式的用途线程池涉及到的类有哪些Executor接口ExecutorService接口Executors工厂类AbstractExecutorService虚类ThreadPoolExecutor普通类ThreadPoolExecutor内部的实现4个拒绝策略 线…

【MySQL】6.MySQL主从复制和读写分离

主从复制 主从复制与读写分离 通常数据库的读/写都在同一个数据库服务器中进行&#xff1b; 但这样在安全性、高可用性和高并发等各个方面无法满足生产环境的实际需求&#xff1b; 因此&#xff0c;通过主从复制的方式同步数据&#xff0c;再通过读写分离提升数据库的并发负载…

【微服务】Nacos(配置中心)

文章目录 1.AP和CP1.基本介绍2.说明 2.Nacos配置中心实例1.架构图2.在Nacos Server加入配置1.配置列表&#xff0c;加号2.加入配置3.点击发布&#xff0c;然后返回4.还可以编辑 3. 创建 Nacos 配置客户端模块获取配置中心信息1.创建子模块 e-commerce-nacos-config-client50002…

快速编译嵌入式Linux(4.9.229)内核(硬件:mini2440)

目录 概述 1 Linux内核介绍 1.1 Linux 内核版本 1.2 下载Linux 内核 2 编译内核 2.1 解压内核 2.2 编译环境 2.3 编译内核 概述 本文主要以硬件板卡mini2440为例&#xff0c;介绍如何从linux内核官网下载一个原生态的内核源码包&#xff0c;通过简单的配置编译适合在AR…

誉天华为认证云计算课程如何

HCIA-Cloud Computing 5.0 课程介绍&#xff1a;掌握华为企业级虚拟化、桌面云部署&#xff0c;具备企业一线部署实施及运维能力 掌握虚拟化技术、网络基础、存储基础等内容&#xff0c;拥有项目实施综合能力 满足企业虚拟化方案转型需求&#xff0c;应对企业日益多样的业务诉求…

excel中批量插入分页符

excel中批量插入分页符&#xff0c;实现按班级打印学生名单。 1、把学生按照学号、班级排序好。 2、选择班级一列&#xff0c;点击数据-分类汇总。汇总方式选择计数&#xff0c;最后三个全部勾选。汇总结果一定要显示在数据的下发&#xff0c;如果显示在上方&#xff0c;后期…

typescript 实现RabbitMQ死信队列和延迟队列 订单10分钟未付归还库存

Manjaro安装RabbitMQ 安装 sudo pacman -S rabbitmq rabbitmqadmin启动管理模块 sudo rabbitmq-plugins enable rabbitmq_managementsudo rabbitmq-server管理界面 http://127.0.0.1:15672/ 默认用户名和密码都是guest。 要使用 rabbitmqctl 命令添加用户并分配权限&#xf…
最新文章