代码训练营Day.22 | 235. 二叉搜索树的最近公共祖先、701. 二叉搜索树中的插入操作、450. 删除二叉搜索树中的节点

【代码随想录训练营】【Day22】第六章|二叉树|235. 二叉搜索树的最近公共祖先|701.二叉搜索树中的插入操作|450.删除二叉搜索树中的节点 阅读详情

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

1. LeetCode链接

力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

2. 题目描述

3. 解法

利用二叉搜索树的特性进行公共节点的判断:

1. 此节点为公共节点:p、q恰好在此节点的左右棵子树上。即,root的val在p、q的val所构成的闭区间内。

2. 如果p、q的val恰好都大于root的val,则只需要考虑root->right

3. 如果p、q都小于root,则只考虑root->left

class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        if (root == NULL) return NULL;
        if (root->val <= p->val && root->val >= q->val || root->val >= p->val && root->val <= q->val) return root;
        else if (p->val > root->val && q->val > root->val) return lowestCommonAncestor(root->right, p, q);
        else return lowestCommonAncestor(root->left, p, q);
    }
};

更精简一点

class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        if (p->val > root->val && q->val > root->val) return lowestCommonAncestor(root->right, p, q);
        else if (p->val < root->val && q->val < root->val) return lowestCommonAncestor(root->left, p, q);
        else return root;
    }
};

迭代法

class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        queue<TreeNode*> qu;
        qu.push(root);
        TreeNode* cur;
        while (!qu.empty()) {
            cur = qu.front();
            qu.pop();
            if (q->val < cur->val && p->val < cur->val) qu.push(cur->left);
            else if (q->val > cur->val && p->val > cur->val) qu.push(cur->right);
            else break;
        }
        return cur;
    }
};

更加精简的:

class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        while(root) {
            if (root->val > p->val && root->val > q->val) {
                root = root->left;
            } else if (root->val < p->val && root->val < q->val) {
                root = root->right;
            } else return root;
        }
        return NULL;
    }
};

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

1. LeetCode链接

力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

2. 题目描述

 

3. 解法

先在二叉搜索树中查询val,直到找到NULL,然后将val插入该NULL。

迭代:

class Solution {
public:
    TreeNode* insertIntoBST(TreeNode* root, int val) {
        TreeNode* a = new TreeNode(val);
        if (root == NULL) return a;
        TreeNode* cur = root;
        while (cur) {
            if (cur->val > val && cur->left != NULL) cur = cur->left;
            else if (cur->val > val && cur->left == NULL) {
                cur->left = a;
                break;
            }
            else if (cur->val < val && cur->right != NULL) cur = cur->right;
            else {
                cur->right = a;
                break;
            }
        }
        return root;
    }
};

递归。相当于将在遍历至NULL的路上,重新连接原本的树,直到遇到NULL,然后把NULL换成val。

1. 参数和返回值。参数:当前节点和val。返回值:当前节点。

2. 终止条件。遇到NULL且将NULL替换为val。

3. 比较root和val确定从左子树走还是右子树走,root->left = root->left  /  root->right = root->right;

class Solution {
public:
    TreeNode* insertIntoBST(TreeNode* root, int val) {
        if (root == NULL) {
            TreeNode* n = new TreeNode(val);
            return n;
        }
        if (root->val > val) root->left = insertIntoBST(root->left, val);
        if (root->val < val) root->right = insertIntoBST(root->right, val);
        return root;
    }
};

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

1. LeetCode链接

力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

2. 题目描述

3. 解法

删除节点后,需要考虑是让左子树上位还是右子树上位。这道题的话,无所谓,暂且让左子树上位吧。这个时候问题来了,右子树该如何安排?

其实这道题目可以看成左子树上位后,将右子树插入左子树,因为两边都是二叉搜索树,且左子树必小于右子树,所以只要简单插入即可。

class Solution {
public:
    TreeNode* insertNode(TreeNode* root, TreeNode* key) {
        if (root == NULL) return key;
        if (key == NULL) return root;
        if (key->val > root->val) root->right = insertNode(root->right, key);
        if (key->val < root->val) root->left = insertNode(root->left, key);
        return root;
    }
    TreeNode* deleteNode(TreeNode* root, int key) {
        if (root == NULL) return NULL;
        if (root->val == key) {
            TreeNode* left = root->left;
            TreeNode* right = root->right;
            delete root;
            return insertNode(left, right);
        }
        if (key > root->val) root->right = deleteNode(root->right, key);
        if (key < root->val) root->left = deleteNode(root->left, key);
        return root;
    }
};

细想的话,其实如果将左子树上位,右子树一定被插在左子树中的最右节点的右节点上;如果让右子树上位,左子树一定被插在最左节点的左节点上。

class Solution {
public:
    TreeNode* deleteNode(TreeNode* root, int key) {
        if (root == NULL) return NULL;
        if (root->val == key) {
            TreeNode* left = root->left;
            TreeNode* right = root->right;
            delete root;
            if (left == NULL) return right;
            if (right == NULL) return left;
            TreeNode* cur = left;
            while (left != NULL && left->right != NULL) left = left->right;
            left->right = right;
            return cur;
        }
        if (key > root->val) root->right = deleteNode(root->right, key);
        if (key < root->val) root->left = deleteNode(root->left, key);
        return root;
    }
};

更巧妙的是,删除当前节点后,最合适的候选节点是左子树最右节点或者右子树最左节点。可以通过交换val值,将root换到底部,然后再遇到root后直接删除。

class Solution {
public:
    TreeNode* deleteNode(TreeNode* root, int key) {
        if (root == nullptr) return root;
        if (root->val == key) {
            if (root->right == nullptr) { // 这里第二次操作目标值:最终删除的作用
                return root->left;
            }
            TreeNode *cur = root->right;
            while (cur->left) {
                cur = cur->left;
            }
            swap(root->val, cur->val); // 这里第一次操作目标值:交换目标值其右子树最左面节点。
        }
        root->left = deleteNode(root->left, key);
        root->right = deleteNode(root->right, key);
        return root;
    }
};

【论文阅读1】机理引导的残差学习用于电池全生命周期状态监测 | Nature Communications 本文提出了一种机理引导的残差学习框架,用于提升电池全生命周期内荷电状态(SOC)和健康状态(SOH)的监测精度。该方法融合等效电路模型的先验知识与机器学习,设计了修正模型和补偿模型两种通用框架。实验验证表明,该方法在三种不同类型电池数据集上均表现出色,SOC和SOH估计误差较传统方法降低50%以上,且在未见工况下仍保持良好外推能力。模型具有强鲁棒性,在减少训练数据量和降低采样频率时性能稳定,并兼具物理可解释性。该框架无需离线测试和运行中校准,为电池安全监测提供了有效解决方案。 阅读详情

相关推荐

Silvaco 学习笔记——物理模型:载流子产生复合模型

对载流子的复合机制进行总结

reactortiger的博客 1万+

代码随想录算法训练营Day22|235.二叉搜索树的最近公共祖先、701.二叉搜索树中的插入操作、450.删除二叉搜索树中的节点

不考虑二叉搜索树这一条件的话,普通的二叉搜索树搜索最近的公共祖先就是昨日的做法,这种做法也能解决二叉搜索树的最近公共祖先。没有用上二叉搜索树这一条件,但也能解题,但效率较低。针对二叉搜索树,我们之前有做过,当对二叉搜索树进行中序编历时,结果是一个递增的数组。即公共祖先,val值必定处于p和q之间。当从根节点向下遍历的过程中,如果遇到节点val值位于p和q之间,那么就寻找到了最近的公共祖先。具体参考代码随想录B站视频。二叉搜索树找祖先就有点不一样了!

github_35852648的博客 2027

HRnet的pytorch实现

HRnet的pytorch实现

奋土的博客 1953

代码随想录算法训练营第day22|235. 二叉搜索树的最近公共祖先 、 701.二叉搜索树中的插入操作 、 450.删除二叉搜索树中的节点

百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。给定一个二叉搜索树的根节点 root 和一个值 key,删除二叉搜索树中的 key 对应的节点,并保证二叉搜索树的性质不变。如图,我们从根节点搜索,第一次遇到 cur节点是数值在[q, p]区间中,即 节点5,此时可以说明 q 和 p 一定分别存在于 节点 5的左子树,和右子树中。如图所示:p为节点6,q为节点9。

qq_60513199的博客 667

如何理解鲁棒性?为什么robustness会翻译为鲁棒性?

鲁棒性,英文为Robustness(承受故障和干扰的能力),是许多复杂系统(包括复杂网络)的关键属性。复杂网络的鲁棒性研究对许多领域都非常重要。本文着重介绍了鲁棒性的基本定义、命名起源、分类区别、提升方法和具体应用,供大家学习参考。

weixin_46880696的博客 8万+

ESP32 STA AP模式下,设备连接 ESP的AP 后无法上网,无法访问域名上网(或者Failed to enable NAPT)

ESP32 STA AP模式下,设备连接 ESP的AP 后无法上网,无法访问域名上网(或者Failed to enable NAPT)1.可能是ESP STA模式未成功连接到路由器,确保 STA 成功连接到外部网络。2.检查 STA 和 AP 的网络配置是否正确,避免子网冲突。3.ESP32的NAPT功能未正确启用,确保 menuconfig 中已启用 IP_NAPT。4.DNS服务器未正确配置。

qq_34885669的博客 1539

代码随想录算法训练营day22||二叉树part08、● 235. 二叉搜索树的最近公共祖先 ● 701.二叉搜索树中的插入操作 ● 450.删除二叉搜索树中的节点

对于二叉搜索树的最近祖先问题,其实要比普通二叉树公共祖先问题 (opens new window)简单的多。不用使用回溯,二叉搜索树自带方向性,可以方便的从上向下查找目标区间,遇到目标区间内的节点,直接返回。最后给出了对应的迭代法,二叉搜索树的迭代法甚至比递归更容易理解,也是因为其有序性(自带方向性),按照目标区间找就行了。读完本篇,大家会发现二叉搜索树删除节点比增加节点复杂的多。因为二叉搜索树添加节点只需要在叶子上添加就可以的,不涉及到结构的调整,而删除节点操作涉及到结构的调整。

qq_40222433的博客 1347

从零开始掌握RDMA拥塞控制:原理、算法与实战解析

本文深入解析了RDMA拥塞控制的核心原理与实战配置。RDMA依赖无损网络保障高性能,其关键在于PFC与ECN两大技术协同防止丢包。文章重点剖析了主流算法DCQCN的工作机制与参数调优,并简要介绍了HPCC与TIMELY等前沿算法。最后提供了在Linux上配置RoCEv2与DCQCN的详细步骤及性能调试方法,帮助读者从零构建稳定的RDMA网络环境。

weixin_28452161的博客 136

代码随想录算法训练营三刷day22 |二叉树之 235. 二叉搜索树的最近公共祖先 701.二叉搜索树中的插入操作 450.删除二叉搜索树中的节点

到这里,大家应该能感受到,如何通过递归函数返回值完成了新加入节点的父子关系赋值操作了,下一层将加入节点返回,本层用。可以有,也可以没有,但递归函数如果没有返回值的话,实现是比较麻烦的,下面也会给出其具体实现代码。说到递归函数的返回值,在上一题中通过递归返回值来加入新节点, 这里也可以通过递归返回值删除节点。终止条件就是找到遍历的节点为null的时候,就是要插入节点的位置了,并把插入的节点返回。这里把添加的节点返回给上一层,就完成了父子节点的赋值操作了,详细再往下看。,其余的情况的最近公共祖先就是根节点。

baimaozi_007的博客 925

常见的AXI总线仲裁器概述-AXI协议理解(一)

SoC 设计广泛采用共享总线式的片上通信,其中的仲裁器是共享总线的关键技术之一。AMBA AXI 总线协议以高性能、高频率的系统设计为目标,适合高带宽、低延迟的系统设计,可以达到高频率的操作而不需要复杂的总线桥,满足众多部件的接口要求,具备高度灵活的互联结构,并且向后兼容 AHB 和 APB 接口。

Paul 安的博客 1万+

银行一表通监管报送系统详解

国家金融监管总局对于“一表通”的总体描述为:通过建立一套明细级、标准化的数据体系和汇总计算规则,将银行机构传送至监管可信区的业务明细数据汇总生成财务指标、监管指标和监管报表,大幅提升监管数据时效性,统一数据标准,实现数据间的穿透和整合,同时改变机构多头报送数据模式,减轻机构报送负担。

银行信息系统应用架构详解 2517

代码随想录算法训练营Day22|Leetcode235二叉搜索树的最近公共祖先、Leetcode701二叉搜索树中的插入操作、Leetcode450删除二叉搜索树中的节点

Day22打卡! 时长:2h 今日感想:深刻理解二叉搜索树的应用~

m0_60979177的博客 917

NVIDIA Omniverse 技术浅析(三):NVIDIA RTX 技术

NVIDIA RTX 技术是 NVIDIA 推出的革命性图形渲染技术,旨在通过硬件加速和软件优化,实现高质量的实时图形渲染。RTX 技术在 NVIDIA Omniverse 平台中扮演着至关重要的角色,为其提供了强大的渲染能力。

m0_75253143的博客 351

代码随想录训练营day22 235.二叉搜索树的最近公共祖先 701.二叉搜索树中的插入操作 450.删除二叉搜索树中的节点

删除二叉搜索树的节点

weixin_55496975的博客 166

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

代码随想录算法训练营Day22|235. 二叉搜索树的最近公共祖先、701.二叉搜索树中的插入操作、450.删除二叉搜索树中的节点

前一题求解二叉树的最近公共祖先,是利用回溯自底向上搜索,遇到一个节点的左子树里有p,右子树里有q,就表明当前节点是最近公共祖先。若是对二叉搜索树进行两节点最近公共祖先查找,可以利用二叉搜索树的结构特点,p和q的最近公共祖先一定满足介于[p,q]区间内的条件,基于此可以分别进行判断搜索。由于是对二叉搜索树进行插入操作,并且插入的新值和二叉搜索树任意节点值都不同,因此只要寻找到合适的叶子节点进行插入操作即可。

m0_68682181的博客 754

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

代码随想录算法训练营 day22| 235. 二叉搜索树的最近公共祖先 、701.二叉搜索树中的插入操作、450.删除二叉搜索树中的节点

剩下的情况,就是cur节点在区间(p->val <= cur->val && cur->val <= q->val)或者 (q->val <= cur->val && cur->val <= p->val)中,那么cur就是最近公共祖先了,直接返回cur。将删除节点(元素7)的左孩子放到删除节点(元素7)的右子树的最左面节点(元素8)的左孩子上,就是把5为根节点的子树移到了8的左孩子的位置。递归函数不用返回值也可以,找到插入的节点位置,直接让其父节点指向插入节点,结束递归,也是可以的。

weixin_42179093的博客 148

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

代码随想录训练营day22|235、二叉搜索树的最近公共祖先;701、二叉搜索树中的插入操作;450、删除二叉搜索树中的节点

235、二叉搜索树的最近公共祖先;701、二叉搜索树中的插入操作;450、删除二叉搜索树中的节点

weixin_43561267的博客 68

代码随想录算法训练营day22|235二叉搜索树的最近公共祖先 |701 二叉搜索树中的插入操作 |450 删除二叉搜索树中的节点

首先在二叉搜索树中的插入操作,大家不用恐惧其重构搜索树,其实根本不用重构。然后在递归中,我们重点讲了如何通过递归函数的返回值完成新加入节点和其父节点的赋值操作,并强调了搜索树的有序性。最后依然给出了迭代的方法,迭代的方法就需要记录当前遍历节点的父节点了,这个和没有返回值的递归函数实现的代码逻辑是一样的。

xinrenne的博客 255

代码随想录训练营day22|235. 二叉搜索树的最近公共祖先 、701.二叉搜索树中的插入操作、450.删除二叉搜索树中的节点

中等中等。

m0_63071531的博客 121

代码随想录算法训练营day22|235. 二叉搜索树的最近公共祖先、701.二叉搜索树中的插入操作、450.删除二叉搜索树中的节点

二叉搜索树递归不用分前中后序,因为他本身就可以看作是排好序的二叉树,且中序遍历的值是升序的。

weixin_64883584的博客 435

代码随想录算法训练营Day22|LC235 二叉搜索树的最近公共祖先&LC701 二叉搜索树的插入操作&LC450 删除二叉搜索树中的节点

一句话总结:删除二叉搜索树中的节点怪复杂的。

qq_62428331的博客 326

代码随想录算法训练营Day 22|LeetCode235 二叉搜索树的最近公共祖先、Leetcode701 二叉搜索树中的插入操作、Leetcode450 删除二叉搜索树中的节点

需要理解一点:从上向下递归遍历,第一次遇到 cur节点是数值在[q, p]区间中,那么cur就是 q和p的最近公共祖先。根据二叉搜索树性质检索,找到NULL位置插入节点即可。(无需重构成平衡树)时间复杂度:O(n)空间复杂度:O(1)时间复杂度:O(n)空间复杂度:O(1)时间复杂度:O(h)空间复杂度:O(n)

qq_52807368的博客 970

代码随想录算法训练营 day22 || 235. 二叉搜索树的最近公共祖先,701.二叉搜索树中的插入操作,450.删除二叉搜索树中的节点

其中关于定位节点位于的方向非常的有必要,然后对于定位到的节点,直接在其位置上就进行操作,因为常理上应当是定位到待删除结点的父节点,然后对父节点的left或者right进行操作,然后返回被删除的节点,但是现在直接在递归上通过返回删除位置,将删除了节点的形成的子树或者路径直接缀连到了原来的树上,真的厉害。思路:昨天的二叉树的最近公共祖先是使用路径重合位置的方法来实现的,并没有采用递归的方式进行实现,其实路径方法也可以用在BST的最近公共祖先上,但是时间效率较低,所以尝试理解学习递归的思想。

旭 448

代码随想录算法训练营 DAY 22 | 235.二叉搜索树的最近公共祖先 701.二叉搜索树中的插入操作 450.删除二叉搜索树中的节点

利用二叉搜索树的性质从上到下去遍历,遇到 cur节点是数值在[p, q]区间中则一定可以说明该节点cur就是p 和 q的公共祖先。问题来了,?如果 从节点5继续向左遍历,那么将错过成为p的祖先, 如果从节点5继续向右遍历则错过成为q的祖先。所以当我们从上向下去递归遍历,第一次遇到 cur节点是数值在[q, p]区间中,那么cur就是 q和p的最近公共祖先。

qq_35904005的博客 520

代码随想录算法训练营day22 |235. 二叉搜索树的最近公共祖先 701.二叉搜索树中的插入操作 450.删除二叉搜索树中的节点

【思考】通过递归函数的返回值完成父子节点的赋值是可以带来便利的。235. 二叉搜索树的最近公共祖先。

2402_83072061的博客 487

代码随想录算法训练营Day22 | 235. 二叉搜索树的最近公共祖先 701.二叉搜索树中的插入操作 450.删除二叉搜索树中的节点

思路:首次进入[p,q]区间。如果在区间右边,则往左遍历,如果在区间左边,则往右遍历。

qq_24817679的博客 314
上一篇: 代码训练营Day.21 | 530. 二叉搜索树的最小绝对差、501. 二叉搜索树中的众数、236. 二叉树的最近公共祖先
下一篇: 代码随想录Day.23 | 669. 修剪二叉搜索树、108. 将有序数组转换为二叉搜索树、538. 把二叉搜索树转换为累加树
怕批龙-_-#
博客等级 码龄6年 313粉丝 36原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值