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

news2025/1/16 13:42:24

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

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

450.删除二叉搜索树节点 

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

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

百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”

例如,给定如下二叉搜索树:  root = [6,2,8,0,4,7,9,null,null,3,5]

示例 1:

输入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 8
输出: 6 
解释: 节点 2 和节点 8 的最近公共祖先是 6。

示例 2:

输入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 4
输出: 2
解释: 节点 2 和节点 4 的最近公共祖先是 2, 因为根据定义最近公共祖先节点可以为节点本身。

说明:

  • 所有节点的值都是唯一的。
  • p、q 为不同节点且均存在于给定的二叉搜索树中。

 

在二叉搜索树(BST)中找到两个节点pq的最低公共祖先(LCA)。在二叉搜索树中,最低公共祖先的特点是它的值在pq的值之间(包括等于pq的情况)。如果pq的值都小于当前节点,那么它们的公共祖先位于当前节点的左子树;如果它们的值都大于当前节点,那么它们的公共祖先位于当前节点的右子树。如果pq分别位于当前节点的两侧,那么当前节点就是它们的最低公共祖先。

代码逻辑

  • 首先检查当前节点是否为NULL,如果是,则返回NULL
  • 然后,如果pq的值都小于当前节点的值,递归地在当前节点的左子树中查找。
  • 如果pq的值都大于当前节点的值,递归地在当前节点的右子树中查找。
  • 如果上述两种情况都不满足(即当前节点的值介于pq的值之间),说明找到了最低公共祖先,返回当前节点。

这个实现利用了BST的性质来优化搜索过程,避免了不必要的遍历。

C++ 

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */

class Solution {

private:
    TreeNode* traversal(TreeNode* cur, TreeNode* p, TreeNode* q) {
        if (cur == NULL) return cur;
                                                        // 中
        if (cur->val > p->val && cur->val > q->val) {   // 左
            TreeNode* left = traversal(cur->left, p, q);
            if (left != NULL) {
                return left;
            }
        }

        if (cur->val < p->val && cur->val < q->val) {   // 右
            TreeNode* right = traversal(cur->right, p, q);
            if (right != NULL) {
                return right;
            }
        }
        return cur;
    }
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        return traversal(root, p, q);
    }
};

python

class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

class Solution:
    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
        # 如果当前节点为空,或者p、q之一就是当前节点,则直接返回当前节点
        if not root or root == p or root == q:
            return root
        
        # 根据BST的性质在左子树或右子树中查找
        if p.val < root.val and q.val < root.val:
            # p和q都在当前节点的左侧
            return self.lowestCommonAncestor(root.left, p, q)
        elif p.val > root.val and q.val > root.val:
            # p和q都在当前节点的右侧
            return self.lowestCommonAncestor(root.right, p, q)
        else:
            # 当前节点就是p和q的最低公共祖先
            return root

迭代法

在二叉搜索树(BST)中查找两个节点的最低公共祖先(LCA)时,可以使用迭代法代替递归来减少空间复杂度。迭代法的核心思想是利用BST的性质:对于树中的任意节点y,如果pq的值都小于y,则pq都在y的左子树中;如果pq的值都大于y,则pq都在y的右子树中;否则,y就是pq的最低公共祖先。

C++

#include <iostream>

struct TreeNode {
    int val;
    TreeNode *left;
    TreeNode *right;
    TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};

class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        // 当前节点初始化为根节点
        TreeNode* current = root;
        while (current) {
            // 如果p和q的值都小于当前节点的值,则在左子树中查找
            if (p->val < current->val && q->val < current->val) {
                current = current->left;
            }
            // 如果p和q的值都大于当前节点的值,则在右子树中查找
            else if (p->val > current->val && q->val > current->val) {
                current = current->right;
            }
            // 否则,当前节点就是LCA
            else {
                return current;
            }
        }
        return nullptr;
    }
};

python

class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

class Solution:
    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
        # 当前节点初始化为根节点
        current = root
        while current:
            # 如果p和q的值都小于当前节点的值,则在左子树中查找
            if p.val < current.val and q.val < current.val:
                current = current.left
            # 如果p和q的值都大于当前节点的值,则在右子树中查找
            elif p.val > current.val and q.val > current.val:
                current = current.right
            # 否则,当前节点就是LCA
            else:
                return current
        return None

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

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

注意,可能存在多种有效的插入方式,只要树在插入后仍保持为二叉搜索树即可。 你可以返回 任意有效的结果 。

示例 1:

输入:root = [4,2,7,1,3], val = 5
输出:[4,2,7,1,3,5]
解释:另一个满足题目要求可以通过的树是:

示例 2:

输入:root = [40,20,60,10,30,50,70], val = 25
输出:[40,20,60,10,30,50,70,null,null,25]

示例 3:

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

提示:

  • 树中的节点数将在 [0, 104]的范围内。
  • -108 <= Node.val <= 108
  • 所有值 Node.val 是 独一无二 的。
  • -108 <= val <= 108
  • 保证 val 在原始BST中不存在。

将一个值插入到二叉搜索树(BST)中,并保持BST的性质。代码中使用了递归方法来找到合适的位置插入新节点。如果树为空,就直接创建一个新节点作为根节点。如果树不为空,递归遍历树直到找到合适的插入位置,然后根据值的大小插入到左子树或右子树。

代码逻辑

  1. 递归遍历:通过traversal函数递归遍历BST,parent变量用于记录当前节点的父节点,以便在找到插入位置时可以直接插入。
  2. 插入新节点:当到达空位置(cur == NULL)时,根据新节点的值与父节点的值的比较结果,决定是将新节点作为左子节点还是右子节点插入。
  3. 树为空的特殊处理:如果BST为空(root == NULL),则直接创建新节点作为根节点。

然而,原始C++代码实现中有一个潜在问题:parent变量的初始值被设置为一个新的TreeNode实例,这个实例并未被真正用作树的一部分,可能会导致内存泄漏或不必要的内存分配。在实际插入操作中,如果根节点非空,parent变量的初始值并未被使用。

C++

class Solution {
private:
    TreeNode* parent;
    void traversal(TreeNode* cur, int val) {
        if (cur == NULL) {
            TreeNode* node = new TreeNode(val);
            if (val > parent->val) parent->right = node;
            else parent->left = node;
            return;
        }
        parent = cur;
        if (cur->val > val) traversal(cur->left, val);
        if (cur->val < val) traversal(cur->right, val);
        return;
    }

public:
    TreeNode* insertIntoBST(TreeNode* root, int val) {
        parent = new TreeNode(0);
        if (root == NULL) {
            root = new TreeNode(val);
        }
        traversal(root, val);
        return root;
    }
};

python

class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

class Solution:
    def insertIntoBST(self, root: TreeNode, val: int) -> TreeNode:
        if not root:
            return TreeNode(val)
        
        def insert(node, val):
            if not node:
                return TreeNode(val)
            if val > node.val:
                node.right = insert(node.right, val)
            else:
                node.left = insert(node.left, val)
            return node
        
        return insert(root, val)

针对C++实现的优化主要集中在避免使用递归来降低空间复杂度,并提高代码执行效率。通过迭代方法寻找正确的插入位置

  • 这个版本的代码使用了迭代方法来寻找新节点的正确插入位置。这种方法避免了递归调用,减少了函数调用栈的使用。
  • 通过迭代遍历树,我们检查新值应该插入到当前节点的左侧还是右侧。如果找到一个空位置(即current->leftcurrent->rightnullptr),就在那里插入新节点。
  • 这种方法保持了二叉搜索树的特性,同时提高了代码的执行效率,特别是在处理大树时。

 

C++

#include <iostream>

struct TreeNode {
    int val;
    TreeNode *left;
    TreeNode *right;
    TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};

class Solution {
public:
    TreeNode* insertIntoBST(TreeNode* root, int val) {
        // 如果树为空,直接创建并返回新节点作为根节点
        if (root == nullptr) {
            return new TreeNode(val);
        }
        
        // 使用迭代寻找正确的插入位置
        TreeNode* current = root; // 当前节点
        while (true) {
            // 如果插入的值大于当前节点的值
            if (val > current->val) {
                // 如果当前节点的右子节点为空,则在此位置插入新节点
                if (current->right == nullptr) {
                    current->right = new TreeNode(val);
                    break; // 插入后退出循环
                } else {
                    // 否则继续向右子树移动
                    current = current->right;
                }
            } else {
                // 如果当前节点的左子节点为空,则在此位置插入新节点
                if (current->left == nullptr) {
                    current->left = new TreeNode(val);
                    break; // 插入后退出循环
                } else {
                    // 否则继续向左子树移动
                    current = current->left;
                }
            }
        }
        
        return root; // 返回未修改的根节点
    }
};

python 

class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

class Solution:
    def insertIntoBST(self, root: TreeNode, val: int) -> TreeNode:
        # 如果根节点为空,直接返回新创建的节点
        if not root:
            return TreeNode(val)
        
        # 定位插入位置
        current = root
        while current:
            # 如果插入的值大于当前节点的值
            if val > current.val:
                # 如果右子节点为空,插入新节点并退出循环
                if not current.right:
                    current.right = TreeNode(val)
                    break
                # 否则,向右子树移动
                else:
                    current = current.right
            # 如果插入的值小于或等于当前节点的值
            else:
                # 如果左子节点为空,插入新节点并退出循环
                if not current.left:
                    current.left = TreeNode(val)
                    break
                # 否则,向左子树移动
                else:
                    current = current.left
        
        return root

450.删除二叉搜索树节点

给定一个二叉搜索树的根节点 root 和一个值 key,删除二叉搜索树中的 key 对应的节点,并保证二叉搜索树的性质不变。返回二叉搜索树(有可能被更新)的根节点的引用。

一般来说,删除节点可分为两个步骤:

  1. 首先找到需要删除的节点;
  2. 如果找到了,删除它。

示例 1:

输入:root = [5,3,6,2,4,null,7], key = 3
输出:[5,4,6,2,null,null,7]
解释:给定需要删除的节点值是 3,所以我们首先找到 3 这个节点,然后删除它。
一个正确的答案是 [5,4,6,2,null,null,7], 如下图所示。
另一个正确答案是 [5,2,6,null,4,null,7]。


示例 2:

输入: root = [5,3,6,2,4,null,7], key = 0
输出: [5,3,6,2,4,null,7]
解释: 二叉树不包含值为 0 的节点

示例 3:

输入: root = [], key = 0
输出: []

实现了在二叉搜索树(BST)中删除一个具有特定键值的节点的功能,并且处理了多种情况,确保删除操作后,树仍然保持BST的性质。

功能分析

  1. 节点未找到:如果当前节点为空,则表示未找到要删除的节点,直接返回nullptr
  2. 找到节点:如果找到了要删除的节点(root->val == key),根据其子节点的情况有以下几种处理方式:
    • 叶子节点:如果节点是叶子节点(没有子节点),则直接删除该节点,并返回nullptr
    • 单子节点:如果节点只有一个子节点(左子节点或右子节点),则删除该节点,并用其子节点替代它,返回替代后的子节点。
    • 双子节点:如果节点有两个子节点,则找到右子树中最左侧的节点(右子树中的最小节点),将要删除节点的左子树接到这个最左侧节点的左侧,然后删除节点,并用其右子节点替代它。
  3. 递归删除:如果要删除的节点值大于当前节点值,递归删除左子树中的节点;如果要删除的节点值小于当前节点值,递归删除右子树中的节点。

C++

class Solution {
public:
    TreeNode* deleteNode(TreeNode* root, int key) {
        if (root == nullptr) return root; // 第一种情况:没找到删除的节点,遍历到空节点直接返回了
        if (root->val == key) {
            // 第二种情况:左右孩子都为空(叶子节点),直接删除节点, 返回NULL为根节点
            if (root->left == nullptr && root->right == nullptr) {
                ///! 内存释放
                delete root;
                return nullptr;
            }
            // 第三种情况:其左孩子为空,右孩子不为空,删除节点,右孩子补位 ,返回右孩子为根节点
            else if (root->left == nullptr) {
                auto retNode = root->right;
                ///! 内存释放
                delete root;
                return retNode;
            }
            // 第四种情况:其右孩子为空,左孩子不为空,删除节点,左孩子补位,返回左孩子为根节点
            else if (root->right == nullptr) {
                auto retNode = root->left;
                ///! 内存释放
                delete root;
                return retNode;
            }
            // 第五种情况:左右孩子节点都不为空,则将删除节点的左子树放到删除节点的右子树的最左面节点的左孩子的位置
            // 并返回删除节点右孩子为新的根节点。
            else {
                TreeNode* cur = root->right; // 找右子树最左面的节点
                while(cur->left != nullptr) {
                    cur = cur->left;
                }
                cur->left = root->left; // 把要删除的节点(root)左子树放在cur的左孩子的位置
                TreeNode* tmp = root;   // 把root节点保存一下,下面来删除
                root = root->right;     // 返回旧root的右孩子作为新root
                delete tmp;             // 释放节点内存(这里不写也可以,但C++最好手动释放一下吧)
                return root;
            }
        }
        if (root->val > key) root->left = deleteNode(root->left, key);
        if (root->val < key) root->right = deleteNode(root->right, key);
        return root;
    }
};

python

class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

class Solution:
    def deleteNode(self, root: TreeNode, key: int) -> TreeNode:
        if not root:
            return None  # 没找到删除的节点
        
        if root.val == key:
            if not root.left and not root.right:
                return None  # 叶子节点,直接删除
            elif not root.left:
                return root.right  # 只有右子节点
            elif not root.right:
                return root.left  # 只有左子节点
            else:
                cur = root.right
                while cur.left:
                    cur = cur.left  # 找到右子树最左侧的节点
                cur.left = root.left  # 将要删除节点的左子树接到cur的左侧
                return root.right  # 删除节点,返回右子节点
        
        elif root.val > key:
            root.left = self.deleteNode(root.left, key)
        else:
            root.right = self.deleteNode(root.right, key)
        
        return root

优化删除节点的代码主要关注减少代码复杂度和提高执行效率。在二叉搜索树(BST)中删除节点时,特别是当目标节点有两个子节点的情况下,一个常见的优化方法是寻找目标节点右子树的最小节点(或左子树的最大节点),然后用它来替代目标节点的值,并在该子树中递归删除那个替代的节点。这种方法避免了直接操作树的结构,只需修改节点的值,简化了节点替换的逻辑。

C++

#include <iostream>

struct TreeNode {
    int val;
    TreeNode *left;
    TreeNode *right;
    TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};

class Solution {
public:
    TreeNode* deleteNode(TreeNode* root, int key) {
        if (!root) return nullptr;

        if (root->val == key) {
            if (!root->left) return root->right;
            if (!root->right) return root->left;
            TreeNode* minNode = root->right;
            while (minNode->left) minNode = minNode->left;
            root->val = minNode->val;  // 替换值
            root->right = deleteNode(root->right, root->val);  // 删除替代节点
        } else if (root->val > key) {
            root->left = deleteNode(root->left, key);
        } else {
            root->right = deleteNode(root->right, key);
        }

        return root;
    }
};

 python

class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

class Solution:
    def deleteNode(self, root: TreeNode, key: int) -> TreeNode:
        if not root:
            return None

        if root.val == key:
            if not root.left:  # 只有右子节点或无子节点
                return root.right
            if not root.right:  # 只有左子节点
                return root.left
            # 有两个子节点,找右子树的最小节点替代删除节点
            minNode = root.right
            while minNode.left:
                minNode = minNode.left
            root.val = minNode.val  # 替换值
            root.right = self.deleteNode(root.right, root.val)  # 删除替代节点
        elif root.val > key:
            root.left = self.deleteNode(root.left, key)
        else:
            root.right = self.deleteNode(root.right, key)
        
        return root

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

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

相关文章

函数指针概念的理解要点

1&#xff1a;理解函数 函数即为代码&#xff0c;代码就应该放在内存中&#xff0c;是内存&#xff0c;就有地址 void CmpFun(int a,int b){if(a>b)printf("最大的数为%d",a);elseprintf("最大的数为%d",b);}int main(){printf("输出函数CmpFu…

redo日志——log buffer与磁盘的交互详解

目录 一、redo日志刷盘机制&#xff08;时机&#xff09; 1、log buffer 空间不足时 2、事务提交 3、后台线程 4、正常关闭服务器 5、checkpoint时 二、数据目录中的redo日志文件 三、redo日志文件格式 log buffer与磁盘交互的最小单位——block 文件格式 四、Log Se…

Generator生成器函数

<script>//三个ajax异步的请求要保证执行的顺序//1. 传统的callback触发回调地狱 痛苦 处理异步任务按照顺序 异步-->同步化执行 代码的可读性更好//2. promise then then语义化明显//3.Generator生成函数//4.async await //ajax函数 xhr//XHR代表 "XMLHttp…

STM32 系统滴答时钟启动过程 SysTick_Config

STM32 系统滴答时钟启动过程 SysTick_Config 1. 系统滴答时钟1.1 简介1.2 配置1.3 启动和更新 1. 系统滴答时钟 1.1 简介 SysTick&#xff1a;系统滴答时钟&#xff0c;属于Cortex-M4内核中的一个外设&#xff0c;24bit向下递减计数。 Systick定时器常用来做延时&#xff0c;…

Jenkins配置node节点

1、添加节点 2、配置node主机的java环境 注意&#xff0c;jdk的位置和版本要和master保持一致 sudo apt-get update sudo apt-get install openjdk-8-jre vim /etc/enviroment写入&#xff1a;export JAVA_HOME/usr/lib/jvm/openjdk-8-jre 按wq!退出 再输入&#xff1a;s…

onlyoffice jsApi调用 进阶二次开发 连接器开发 api操作office文档 demo可直接运行测试

office这个体系分为四个大教程 1、【document server文档服务器基础搭建】 2、【连接器(connector)或者jsApi调用操作office】-进阶 3、【document builder文档构造器使用】-进阶 4、【Conversion API(文档转化服务)】-进阶 如果需要连接器&#xff0c;可以查看&#xff1a…

动态gif怎么在线生成?一招快速搞定gif动画

在我们生活沟通中都会运用到各种生动有趣gif动图。很多时候我们在使用gif动图的时候都需要从网上下载找起来很麻烦。那么&#xff0c;自己怎么制作gif动态图片呢&#xff1f;很简单&#xff0c;使用Gif制作&#xff08;https://www.gif.cn/&#xff09;工具&#xff0c;不需要下…

前端|Day3:CSS基础(黑马笔记)

Day3:CSS基础 目录 Day3:CSS基础一、CSS初体验二、CSS引入方式三、选择器1.标签选择器2.类选择器3.id选择器4.通配符选择器 四、盒子尺寸和背景色五、文字控制属性1.字体大小2.字体样式&#xff08;是否倾斜&#xff09;3.行高单行文字垂直居中 4.字体族5.font复合属性6.文本缩…

XGB-7: 特征交互约束

决策树是发现自变量&#xff08;特征&#xff09;之间交互关系的强大工具。在遍历路径中一起出现的变量是相互交互的&#xff0c;因为子节点的条件取决于父节点的条件。例如&#xff0c;在下图中&#xff0c;红色突出显示的路径包含三个变量&#xff1a; x 1 x_1 x1​、 x 7 x_…

facebook群控如何做?静态住宅ip代理在多账号运营重的作用

在进行Facebook群控时&#xff0c;ip地址的管理是非常重要的&#xff0c;因为Facebook通常会检测ip地址的使用情况&#xff0c;如果发现有异常的使用行为&#xff0c;比如从同一个ip地址频繁进行登录、发布内容或者在短时间内进行大量的活动等等&#xff0c;就会视为垃圾邮件或…

探究二维码技术:连接现实与数字世界的桥梁

title: 探究二维码技术&#xff1a;连接现实与数字世界的桥梁 date: 2024/2/19 13:15:36 updated: 2024/2/19 13:15:36 tags: 二维码技术数据编码纠错算法图像处理商业应用安全验证实时交互 引言&#xff1a; 二维码已经成为现代社会中广泛应用的一种技术工具。它不仅在商业领…

C#,二进制数的按位交换(Bits swap)的算法与源代码

数字在指定位置指定位数的交换是常见算法。 1 源程序 using System; using System.Text; using System.Collections; using System.Collections.Generic; namespace Legalsoft.Truffer.Algorithm { public static partial class Algorithm_Gallery { /// <…

Java——Stream流的学习

在开发过程中&#xff0c;经常或忽略流的使用&#xff0c;导致用的不熟练&#xff0c;于是抽时间系统的学习下stream的使用&#xff0c;找了哔哩哔哩的教程跟着看看练练。 准备工作 创建Book、Aurhor实体类&#xff0c;初始化数据 public static List<Author> getAuth…

图形渲染基础学习

原文链接&#xff1a;游戏开发入门&#xff08;三&#xff09;图形渲染_如果一个面只有三个像素进行渲染可以理解为是定点渲染吗?-CSDN博客 游戏开发入门&#xff08;三&#xff09;图形渲染笔记&#xff1a; 渲染一般分为离线渲染与实时渲染&#xff0c;游戏中我们用的都是…

浙大恩特客户资源管理系统 FollowAction SQL注入漏洞复现

0x01 产品简介 浙大恩特客户资源管理系统是一款针对企业客户资源管理的软件产品。该系统旨在帮助企业高效地管理和利用客户资源,提升销售和市场营销的效果。 0x02 漏洞概述 浙大恩特客户资源管理系统 FollowAction 接口处存在SQL注入漏洞,未经身份认证的攻击者可以利用该漏…

补-代码随想录第23天|● 669. 修剪二叉搜索树 ● 108.将有序数组转换为二叉搜索树 ● 538.把二叉搜索树转换为累加树

二叉树最后一天 ● 669. 修剪二叉搜索树思路一&#xff1a;递归递归三部曲代码&#xff1a; 思路二&#xff1a;迭代代码&#xff1a; ● 108.将有序数组转换为二叉搜索树思路&#xff1a;递归代码;[左闭右闭] ● 538.把二叉搜索树转换为累加树思路&#xff1a;递归 代码&#…

onlyoffice基础环境搭建+部署+demo可直接运行 最简单的入门

office这个体系分为四个大教程 1、【document server文档服务器基础搭建】 2、【连接器(connector)或者jsApi调用操作office】-进阶 3、【document builder文档构造器使用】-进阶 4、【Conversion API(文档转化服务)】-进阶 如果需要连接器&#xff0c;可以查看&#xff1a;onl…

【SpringBoot3】Spring Security 常用注解

注&#xff1a;本文基于Spring Boot 3.2.1 以及 Spring Security 6.2.1 Spring Security 6 的常用注解包括以下几种&#xff0c;通过这些注解可以更加方便的控制资源权限。 Secured &#xff1a;方法执行前检查&#xff0c;直接判断有没有对应的角色PreAuthorize&#xff1a;方…

Jmeter实现阶梯式线程增加的压测

安装相应jmeter 插件 1&#xff1a;安装jmeter 管理插件&#xff1a; 下载地址&#xff1a;https://jmeter-plugins.org/install/Install/&#xff0c;将下载下来的jar包放到jmeter文件夹下的lib/ext路径下&#xff0c;然后重启jmeter。 2&#xff1a;接着打开 选项-Plugins Ma…

【FastAPI】P3 请求与响应

目录 请求路径参数查询参数 响应JSON 响应文本响应返回 Pydantic 模型 在网络通讯中&#xff0c;请求&#xff08;Request&#xff09; 与 响应&#xff08;Response&#xff09; 扮演着至关重要的角色&#xff0c;它们构成了客户端与服务器间互动的根本理念。 请求&#xff0…