代码随想录算法训练营三期 day 23 - 二叉树(9)

news2025/4/16 14:19:00

669. 修剪二叉搜索树

原文链接:669. 修剪二叉搜索树
题目链接:669. 修剪二叉搜索树
视频链接:669. 修剪二叉搜索树
请添加图片描述
在上图中我们发现结点 0 0 0 并不符合区间要求,那么将结点 0 0 0 的右孩子 结点 2 2 2 直接赋给 结点 3 3 3 的左孩子就可以了(就是把结点 0 0 0 从二叉树中移除)。

递归法

(1) 确定递归函数参数及返回值:
可以通过递归函数的返回值来移除结点。

    TreeNode* trimBST(TreeNode* root, int low, int high) {

(2) 确定终止条件:
遇到空节点返回。

        if (root == NULL) {
            return NULL;
        }

(3) 确定单层递归逻辑:
如果 r o o t root root(当前结点)的数值小于 l o w low low 的数值,那么应该递归右子树,并返回右子树符合条件的头结点。

        if (root -> val < low) {
            TreeNode* right = trimBST(root -> right, low, high);
            return right;
        }

如果 r o o t root root(当前结点)的数值大于 h i g h high high 的数值,那么应该递归左子树,并返回左子树符合条件的头结点。

        if (root -> val > high) {
            TreeNode* left = trimBST(root -> left, low, high);
            return left;
        }

接下来要将下一层处理完左子树的结果赋给 r o o t → l e f t root\rightarrow left rootleft,处理完右子树的结果赋给 r o o t → r i g h t root\rightarrow right rootright
最后返回 r o o t root root 结点,代码如下:

        root -> left = trimBST(root -> left, low, high);
        root -> right = trimBST(root -> right, low, high);
        return root;

请添加图片描述
在上图中:
如下代码相当于把 结点 0 0 0 的右孩子(结点 2 2 2)返回给上一层:

        if (root -> val < low) {
            TreeNode* right = trimBST(root -> right, low, high);
            return right;
        }

然后 如下代码 相当于用结点 3 3 3 的左孩子把下一层返回的 结点 0 0 0 的右孩子(结点 2 2 2) 接住。

        root -> left = trimBST(root -> left, low, high);

此时结点 3 3 3 的左孩子就变成了结点 2 2 2, 把结点 0 0 0 删除了。

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

总体代码如下:

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

108. 将有序数组转换为二叉搜索树

原文链接:108. 将有序数组转换为二叉搜索树
题目链接:108. 将有序数组转换为二叉搜索树
视频链接:构造平衡二叉搜索树!| LeetCode:108. 将有序数组转换为二叉搜索树
有序数组构造二叉树,分割点就是数组中间位置的结点。
如果数组长度为偶数,中间结点有 2 2 2 个,可以构成不同的平衡二叉树。

递归法

(1) 确定递归函数参数及返回值:
本题要构造二叉树,依然用递归函数的返回值来构造中结点的左右孩子。
参数:传入的数组,然后就是左下标 l e f t left left 和 右下标 r i g h t right right

    // 左闭右闭区间 [left, right]
    TreeNode* traversal(vector<int>& nums, int left, int right)

注意定义的时候是左闭右闭区间,分割的时候也要坚持左闭右闭区间(循环不变量)。
(2) 确定终止条件:
因为是左闭右闭区间,所以当 l e f t > r i g h t left > right left>right 的时候,就是空结点了。

        if (left > right) {
            return NULL;
        }

(3) 确定单层递归的逻辑:
寻找中间结点并构造中间结点:

        int mid = left + (right - left) / 2;
        TreeNode* root = new TreeNode(nums[mid]);

接着划分区间, r o o t root root 的左孩子 接住 下一层左区间的构造结点,右孩子 接住 下一层右区间的构造结点。最后返回 r o o t root root 结点。
单层递归整体代码如下:

        int mid = left + (right - left) / 2;
        TreeNode* root = new TreeNode(nums[mid]);
        root -> left = traversal(nums, left, mid - 1);
        root -> right = traversal(nums, mid + 1, right);
        return root;

这里 int mid = left + ((right - left) / 2); 的写法相当于是如果数组长度为偶数,中间位置有两个元素,取靠左边的
整体代码如下:

class Solution {
private:
    TreeNode* traversal(vector<int>& nums, int left, int right) {
        if (left > right) {
            return NULL;
        }
        int mid = left + (right - left) / 2;
        int rootValue = nums[mid];
        TreeNode* root = new TreeNode(rootValue);
        root -> left = traversal(nums, left, mid - 1);
        root -> right = traversal(nums, mid + 1, right);
        return root;
    }
public:
    TreeNode* sortedArrayToBST(vector<int>& nums) {
        TreeNode* root = traversal(nums, 0, nums.size() - 1);
        return root;
    }
};

538. 把二叉搜索树转换为累加树

原文链接:538. 把二叉搜索树转换为累加树
题目链接:538. 把二叉搜索树转换为累加树
视频链接:538. 把二叉搜索树转换为累加树
反中序遍历(右中左) 遍历二叉树,顺序累加即可。

递归法

需要 p r e pre pre 指针记录当前遍历结点 c u r cur cur 的前一个结点。
(1) 递归函数参数及返回值:
要遍历整棵树,递归函数不需要返回值。
需要一个全局变量 p r e pre pre 来记录前一个结点的数值。

    int pre = 0;
    void traversal(TreeNode* cur) {

(2) 确定终止条件:

        if (cur == NULL) {
            return ;
        }

(3) 确定单层递归逻辑:
c u r cur cur 加上前一个结点的值,并把 c u r cur cur 的值赋给 p r e pre pre

        traversal(cur -> right);            // 右
        cur -> val += pre;                  // 中
        pre = cur -> val;
        traversal(cur -> left);             // 左

代码如下:

class Solution {
private:
    int pre = 0;
    void traversal(TreeNode* cur) {
        if (cur == NULL) {
            return ;
        }
        traversal(cur -> right);            // 右
        cur -> val += pre;                  // 中
        pre = cur -> val;
        traversal(cur -> left);             // 左
    }
public:
    TreeNode* convertBST(TreeNode* root) {
        traversal(root);
        return root;
    }
};

迭代法

代码如下:

class Solution {
private:
    int pre = 0;
    void traversal(TreeNode* root) {
        stack<TreeNode*> st;
        TreeNode* cur = root;
        while (cur != NULL || !st.empty()) {
            if (cur != NULL) {
                st.push(cur);
                cur = cur -> right;             // 右
            } else {
                cur = st.top();                 // 中
                st.pop();
                cur -> val += pre;
                pre = cur -> val;
                cur = cur -> left;              // 左
            }
        }
    }
public:
    TreeNode* convertBST(TreeNode* root) {
        traversal(root);
        return root;
    }
};

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

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

相关文章

Java设计模式 (1) —— Iterator迭代器模式

拿到这个话题&#xff0c;首先搞清楚&#xff1a;什么是迭代器&#xff1f; 大家都学过 for-i 循环&#xff0c;for-i循环的本质就是 通过i 或者 i-- &#xff0c;以实现 从数据的一端 一个一个地遍历数据元素&#xff0c;直到另一端的最后一个元素&#xff0c;将这里 i 的通用…

【Linux】基础IO —— 深入理解文件系统 | 软硬链接

&#x1f308;欢迎来到Linux专栏~~ 深入理解文件系统 (꒪ꇴ꒪(꒪ꇴ꒪ )&#x1f423;,我是Scort目前状态&#xff1a;大三非科班啃C中&#x1f30d;博客主页&#xff1a;张小姐的猫~江湖背景快上车&#x1f698;&#xff0c;握好方向盘跟我有一起打天下嘞&#xff01;送给自己的…

安全需求和挑战

安全需求和挑战 从风险管理的角度讲&#xff0c;主要就是管理资产、威胁、脆弱性 和防护措施及其相关关系&#xff0c;最终保障云计算平台的持续安全&#xff0c;以及 其所支撑的业务的安全。 云计算平台是在传统 IT技术的基础上&#xff0c;增加了一个虚拟化 层&#xff0c;并…

大数据之——Hive

目录1. Hive 基本概念1.1 什么是 Hive1.2 Hive 的优缺点1.2.1 优点1.2.2 缺点1.3 Hive 架构原理2. Hive 安装2.1 Hive 安装地址2.2Hive 安装部署2.3MySQL 安装2.4 Hive 元数据配置到 MySQL2.4.1 拷贝驱动2.4.2 配置 Metastore 到 MySQL2.4.3 再次启动 Hive2.5 使用元数据服务的…

让学前端不再害怕英语单词(二)

写了本专栏的第一章让学前端不再害怕英语单词&#xff08;一&#xff09;后&#xff0c;反响热度还是比较高的&#xff0c;截止现在已经有20个收藏量了&#xff0c;所以趁热打铁来更第二章 第一章我们简单的介绍了html&#xff0c;css和js的部分高频单词&#xff0c;因为html要…

S32K144的GPIO使用

程序初始化前线使用Components工具对时钟和GPIO进行配置&#xff0c;然后再main函数里面初始化。 时钟配置参考&#xff1a; S32K144之时钟配置 - 明明1109 - 博客园 (cnblogs.com) gpio配置 S32K SDK使用详解之PinSettings组件配置与使用详解(S32K1xx PORT 和GPIO模块)_嵌…

jdk1.8新特性简介

一、引言 jdk1.8出来已经一段时间了&#xff0c;现在1.9也已经出来了&#xff0c;但是很多公司&#xff08;我们公司也一样&#xff09;不太愿意升级到高版本的jdk&#xff0c;主要是有老的项目要维护&#xff0c;还有升级的话配套的框架也要升级&#xff0c;要考虑的细节事情太…

实训素材纯HTML+CSS代码 (教育主题 3页 )

⛵ 源码获取 文末联系 ✈ Web前端开发技术 描述 网页设计题材&#xff0c;DIVCSS 布局制作,HTMLCSS网页设计期末课程大作业 | 家乡旅游景点 | 家乡民生变化 | 介绍自己的家乡 | 我的家乡 | 家乡主题 | HTML期末大学生网页设计作业&#xff0c;Web大学生网页 HTML&#xff1a;结…

SpringMVC具体工作流程(保姆教学)

目录 文章目录[toc]一、SpingMVC的常用组件二、[SpringMVC](https://so.csdn.net/so/search?qSpringMVC&spm1001.2101.3001.7020)的工作流程一、SpingMVC的常用组件 1&#xff09;DispatcherServlet 是一种前端控制器&#xff0c;由框架提供。 作用&#xff1a;统一处理请…

基于Simulink宽带单基地雷达系统仿真(附源码)

目录 一、探索示例 1.1 收发器 1.2 信号处理子系统 1.3 渠道 1.4 目标子系统 二、结果和显示 三、总结 四、程序 本示例演示如何仿真宽带雷达系统。当雷达系统的带宽超过系统中心频率的5%时&#xff0c;通常被认为是宽带的。对于此示例&#xff0c;将使用 10% 的带宽。 …

智慧供应链解决方案-最新全套文件

智慧供应链解决方案-最新全套文件一、建设背景二、建设思路三、建设方案智慧供应链具有以下特点1、高度智能化2、全流程数字化3、信息系统互联互通四、获取 - 智慧供应链全套最新解决方案合集一、建设背景 智慧供应链是结合物联网技术和现代供应链管理的理论、方法和技术&…

ES6 入门教程 16 Reflect 16.1 概述

ES6 入门教程 ECMAScript 6 入门 作者&#xff1a;阮一峰 本文仅用于学习记录&#xff0c;不存在任何商业用途&#xff0c;如侵删 文章目录ES6 入门教程16 Reflect16.1 概述16 Reflect 16.1 概述 Reflect对象与Proxy对象一样&#xff0c;也是 ES6 为了操作对象而提供的新 API…

nodejs校园二手交易管理系统vue

本系统的设计主要是为给网上用户提供购物方便&#xff0c;所以应该完成以下目标&#xff1a; (1) 登录、注册。用户要想在交易系统中购买商品&#xff0c;就必须先登录系统。如果不是会员&#xff0c;就必须先注册&#xff0c;然后才能登录系统。 (2) 查找商品。用户可以查找自…

求程序段中++x或者x++的频度,时间复杂度、执行次数

以下程序段中"x"的执行频度&#xff1f; 频度就是执行次数for i:1 to n then;for j:1 to n then;x;i1时 内圈for执行n次...in时 内圈执行n次我的理解&#xff1a;外圈for从1到n&#xff0c;有效循环是n次&#xff0c;外圈每循环一次&#xff0c;内圈循环n次&#…

C语言源代码系列-管理系统之学生籍贯信息

往期文章分享点击跳转>《导航贴》- Unity手册&#xff0c;系统实战学习点击跳转>《导航贴》- Android手册&#xff0c;重温移动开发 &#x1f449;关于作者 众所周知&#xff0c;人生是一个漫长的流程&#xff0c;不断克服困难&#xff0c;不断反思前进的过程。在这个过…

Python 3.11新功能:错误信息回溯

错误信息回溯 长按关注《Python学研大本营》&#xff0c;加入读者群&#xff0c;分享更多精彩 扫码关注《Python学研大本营》&#xff0c;加入读者群&#xff0c;分享更多精彩 Python 3.11于2022 年 10 月 24 日发布。这个最新版本的 Python 速度更快&#xff0c;对用户更友好…

QT源码拾贝0-5(qimage和qpainter)

目录 0 qt源码查看方法 1. qimage.cpp中线程池使用方法 2. qpainter_p.h中SmallStack模板元结构体存放智能指针 3. qpainter.cpp的保存函数&#xff0c;状态对象赋值使用std::exchange函数 4. qpainter.cpp中获得类对象的方法 5. qpainter.cpp中QChar字节操作&…

代码随想录算法训练营三期 day 22 - 二叉树(8)

235. 二叉搜索树的最近公共祖先 原文链接&#xff1a;235. 二叉搜索树的最近公共祖先 题目链接&#xff1a;235. 二叉搜索树的最近公共祖先 在 有序树 里: 从上向下递归遍历&#xff0c;第一次遇到 curcurcur 结点的数值在 p,qp, qp,q 结点对应数值的闭区间中&#xff0c;那么…

内网渗透神器CobaltStrike之Beacon详解(三)

Beacon的种类 HTTP Beacon和HTTPS Beacon 这两个beacon的原理是通过发送http请求与受害主机通信来传达命令, 以此实现控制效果 优点是传输数据快, 缺点时隐蔽性差, 容易被防火墙或内网审计工具拦截 TCP Beacon 自CS4.0版本之后只有反向的TCP Beacon可用, 基于TCP协议的通信…

取证初级案例操作大纲

文章目录**取证初级案例操作大纲**1) 证据文件中有没有存在被删除的Doc文档&#xff1f;如果有的话&#xff0c;请导出并记录文件名及路径&#xff1a;2) 证据文件中有没有存在被删除的图片&#xff1f;如果有的话&#xff0c;请记录文件名及路径&#xff1a;3) 证据文件中哪几…