【面试HOT200】二叉树的构建二叉搜索树篇

系列综述:
💞目的:本系列是个人整理为了秋招面试的,整理期间苛求每个知识点,平衡理解简易度与深入程度。
🥰来源:材料主要源于【CodeTopHot200】进行的,每个知识点的修正和深入主要参考各平台大佬的文章,其中也可能含有少量的个人实验自证,所有代码均优先参考最佳性能。
🤭结语:如果有帮到你的地方,就点个赞关注一下呗,谢谢🎈🎄🌷!!!
🌈【C++】秋招&实习面经汇总篇


文章目录

    • 二叉树的构建
      • 基础知识
        • 654. 构建二叉树*
      • 相关题目
        • 105. 从前序与中序遍历序列构造二叉树
        • 106. 从中序与后序遍历序列构造二叉树
    • 二叉搜索树(考察较少,留后处理)
      • 基础知识
      • 相关题目
        • 98. 验证二叉搜索树
        • 530. 二叉搜索树的最小绝对差
        • 236. 二叉树的最近公共祖先
        • 235. 二叉搜索树的最近公共祖先
        • 450. 删除二叉搜索树中的节点
        • 669. 修剪二叉搜索树
        • 108. 将有序数组转换为二叉搜索树
        • 669. 修剪二叉搜索树
    • 参考博客


😊点此到文末惊喜↩︎

二叉树的构建

基础知识

654. 构建二叉树*
  1. 654. 最大二叉树
    • 通过始末位置指示容器范围,避免每次调用的vector创建开销
TreeNode* constructMaximumBinaryTree(vector<int>& nums) {
    auto self = [&](auto &&self, int left, int right)->TreeNode*{
        // 递归出口
        if (left > right) return nullptr;
        // 如何划分:查找区间中的最大根节点
        int max_pos = left;
        for (int i = left+1; i <= right; ++i) {
            if (nums[i] > nums[max_pos]) 
                max_pos = i;
        }
        // 建立根节点,左递归,右递归
        TreeNode *root = new TreeNode(nums[max_pos]);
        root->left = self(self, left, max_pos-1);
        root->right = self(self, max_pos+1, right);
        // 返回根节点
        return root;
    };
    TreeNode *root = self(self, 0, nums.size()-1);
    return root;
}

相关题目

105. 从前序与中序遍历序列构造二叉树
  1. 105. 从前序与中序遍历序列构造二叉树

    在这里插入图片描述
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder){
    auto self = [&](auto &&self, 
    int pre_left, int pre_right, int in_left, int in_right)->TreeNode*{
    	// 递归出口:只需要前序的左右指针符合即可
        if (pre_left > pre_right) return nullptr;
		
        // 1. 将前序序列的第一个结点作为根节点
        TreeNode *root = new TreeNode(preorder[pre_left]);
        // 2. 找到前序序列的第一个结点在后序序列中的位置作为划分 
        int pivot = in_left; 
        for (; pivot <= in_right; ++pivot){ // key:注意初始化
            if (inorder[pivot] == preorder[pre_left]) //  key:查找中序的pivot
                break;
        }
        // 3. 计算前序数组中的划分位置
        int pre_pivot = pre_left + pivot - in_left;
        // 4. 建立二叉树
        root->left = self(self, pre_left+1, pre_pivot, in_left, pivot-1);
        root->right = self(self, pre_pivot+1, pre_right, pivot+1, in_right);
		
        return root;
    };
    return self(self, 0, preorder.size()-1, 0, inorder.size()-1);
}
106. 从中序与后序遍历序列构造二叉树
  1. 106. 从中序与后序遍历序列构造二叉树

    • 通过始末位置指示容器范围,避免每次调用的vector创建开销
TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
    auto self = [&](auto &&self, 
    int in_left, int in_right, int post_left, int post_right)->TreeNode*{
        // 递归出口
        if (post_left > post_right) return nullptr;
        // 建立根结点
        TreeNode *root = new TreeNode(postorder[post_right]);
        // 在中序数组中查找划分位置
        int pivot = in_left;
        for (; pivot <= in_right; ++pivot) {
            if (inorder[pivot] == postorder[post_right])
                break;
        }
        // 建立左右子树
        int post_pivot = post_right - (in_right - pivot);// key:注意括号
        root->left = self(self, in_left, pivot-1, post_left, post_pivot-1);
        root->right = self(self, pivot+1, in_right, post_pivot, post_right-1);

        return root;
    };
    return self(self, 0, inorder.size()-1, 0, postorder.size()-1);
}

二叉搜索树(考察较少,留后处理)

基础知识

相关题目

98. 验证二叉搜索树
  1. 98. 验证二叉搜索树
    • 中序遍历下,输出的二叉搜索树节点的数值是有序序列
    // **********中序遍历,形成一个递增数组**************
    vector<int> vec;
    void inorder(TreeNode *root){
        if(root == nullptr) return ;
        inorder(root->left);
        vec.push_back(root->val);
        inorder(root->right);
    }
    // 判断是否中序遍历的数组是递增的
    bool isValidBST(TreeNode* root){
        inorder(root);
        for(int i = 0; i < vec.size()-1; ++i){
            if(vec[i] >= vec[i+1])// 二叉搜索树的中序排列是严格递增的
                return false;
        }
        return true;
    }
    
    // *********************纯递归**********************
    bool isValid(TreeNode* current,long left,long right){
        // 单层逻辑
        if(current==nullptr) 
            return true;
        else if(current->val<=left||current->val>=right) 
            return false;
        // 递归
        return isValid(current->left,left,current->val)
        		&&isValid(current->right,current->val,right);
    }
    bool isValidBST(TreeNode* root) {
        return isValid(root,LONG_MIN,LONG_MAX);
    }
    

530. 二叉搜索树的最小绝对差
  1. 530. 二叉搜索树的最小绝对差
    • 思路:中序遍历下,输出的二叉搜索树节点的数值是有序序列。顺序判断相邻值的绝对值,保存最小的即可
    • 双指针在树内应用,双指针本质是对于一个序列的遍历。
    int getMinimumDifference(TreeNode* root) {
        // 初始化条件
        stack<TreeNode*> st;
        if(root != nullptr) st.push(root);
        int res = INT_MAX;
        TreeNode *prior = new TreeNode(-1000000);
    
        while(!st.empty()){
            TreeNode* cur = st.top();
            if(cur != nullptr){
                st.pop();
    			// 中序遍历
                if(cur->right) st.push(cur->right);
                st.push(cur);
                st.push(nullptr);
                if(cur->left) st.push(cur->left);
            }else{
                st.pop();
                cur = st.top();
                st.pop();
                // 节点处理
                res = min(res, cur->val - prior->val);
                prior = cur;// 迭代条件
                
            }
        }
        return res;
    }
    

236. 二叉树的最近公共祖先
  1. 236. 二叉树的最近公共祖先
    • 后序遍历是一个天然的自低向上的回溯过程
    • 状态的向上传递:通过判断左右子树是否出现了p和q,如果出现p或q则通过回溯值上传到父节点
        TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
            if(root == NULL)
                return NULL;
            // 每次对返回的结点进行
            if(root == p || root == q) 
                return root;
                
            TreeNode* left =  lowestCommonAncestor(root->left, p, q);
            TreeNode* right = lowestCommonAncestor(root->right, p, q);
           	// 结点的处理是:尽量返回结点
            if(left == NULL)
                return right;
            if(right == NULL)
                return left;      
            if(left && right) // p和q在两侧
                return root;
            
            return NULL; // 必须有返回值
        }
    

235. 二叉搜索树的最近公共祖先
  1. 235. 二叉搜索树的最近公共祖先
    • 思路:自上而下搜索,遇到的第一个节点值在p和q之间的值即为最近公共祖先
    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;
    }
    

450. 删除二叉搜索树中的节点
  1. 450. 删除二叉搜索树中的节点
    • 思路:框架
    TreeNode* deleteNode(TreeNode* root, int key) {
        // 健壮性检查
        if(root == nullptr) return nullptr;
        // 基本初始化
        TreeNode *cur = root;
        TreeNode *prior = root;
        while (cur != nullptr){
            // 符合条件值的处理
            if(cur->val == key){
                if(cur->left == nullptr || cur->right == nullptr){
                    // 两个都空
                    if(cur->left == nullptr && cur->right == nullptr) 
                        return nullptr;
                    // 被删除节点只有一个孩子或均为空
                    if(key < prior->val){// cur是左子树
                        prior->left = cur->right;
                        return root;  
                    }else{
                        prior->right n = cur->right;
                        return root; 
                    }
                }else{
                    // 被删除节点有两个孩子
                    TreeNode *curLeft = cur->left;
                    cur = cur->right;
                    while(cur->left != nullptr){
                        cur = cur->left;
                    }
                    cur->left = curLeft;
    
                    if(key < prior->val){// cur是左子树
                        prior->left = prior->left->right;
                        return root;  
                    }else{
                        prior->right = prior->right->right;
                        return root; 
                    }
                    
                    
                }
                
            }
    
            prior = cur;// 前迭代
            // 左右节点处理
            if(key < cur->val){
                if(cur->left){
                    cur = cur->left;
                }else{// 找不到
                    return root;
                }
            }else{
                if(cur->right){
                    cur = cur->right;
                }else{// 找不到
                    return root;
                }
            }
            
        }
    
        return root;
    
    }
    

669. 修剪二叉搜索树
  1. 669. 修剪二叉搜索树
    // 1. 确定递归函数的返回类型及参数,返回类型是递归算法的输出值类型,参数是递归算法的输入
    TreeNode* trimBST(TreeNode* root, int low, int high) {
        // 2. 递归终止条件
        if (root == nullptr ) return nullptr;
    
        // 3.节点处理:return保留的状态
        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;
        }
    
        // 4.迭代条件
        root->left = trimBST(root->left, low, high); // root->left接入符合条件的左孩子
        root->right = trimBST(root->right, low, high); // root->right接入符合条件的右孩子
        return root;
    }
    

108. 将有序数组转换为二叉搜索树
  1. 108. 将有序数组转换为二叉搜索树
    TreeNode* traversal(vector<int>& nums, int left, int right) {
        // 递归出口
        if (left > right) return nullptr;
        // 运算
        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;
    }
    // 主调函数
    TreeNode* sortedArrayToBST(vector<int>& nums) {
        TreeNode* root = traversal(nums, 0, nums.size() - 1);
        return root;
    }
    

669. 修剪二叉搜索树
  1. 669. 修剪二叉搜索树
    // 1. 确定递归函数的返回类型及参数,返回类型是递归算法的输出值类型,参数是递归算法的输入
    TreeNode* trimBST(TreeNode* root, int low, int high) {
        // 2. 递归终止条件
        if (root == nullptr ) return nullptr;
    
        // 3.节点处理:return保留的状态
        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;
        }
    
        // 4.迭代条件
        root->left = trimBST(root->left, low, high); // root->left接入符合条件的左孩子
        root->right = trimBST(root->right, low, high); // root->right接入符合条件的右孩子
        return root;
    }
    

少年,我观你骨骼清奇,颖悟绝伦,必成人中龙凤。
不如点赞·收藏·关注一波

🚩点此跳转到首行↩︎

参考博客

  1. 「代码随想录」47. 全排列 II:【彻底理解排列中的去重问题】详解
  2. codetop

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

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

相关文章

vr工业制造流程3D模拟仿真可视化展示

工业仿真3D数字化展示系统具有多方面的独特之处&#xff0c;主要体现在以下几个方面&#xff1a; 1、真实感和交互性&#xff1a;该系统可以将实际的工业设备、产品、场景等进行数字化建模&#xff0c;通过三维图形技术将其呈现在计算机屏幕上&#xff0c;使用户可以在虚拟环境…

ospf选路

问题描述 R6通过主备份路径访问LSP&#xff08;R1&#xff09;&#xff0c;主为R2&#xff0c; 备为R3 解决方案 路由器1看作LSP&#xff0c;配置loopback 0 ,地址为1.1.1.1 供测试使用&#xff1b;路由器 236, LSW4和LSW5&#xff0c; 运行ospf处于相同区域&#xff0c;建立…

【荣誉】科东软件荣获广州市软件行业协会双料大奖!

软件产业在数字经济中扮演着基础支撑的角色&#xff0c;对于优化产业结构、提高自主可控、赋能整体经济高质量发展具有关键作用。 近日&#xff0c;广州市软件行业第七届会员大会第三次会议成功召开&#xff01;此次会议旨在回顾过去一年的行业发展&#xff0c;展望未来的趋势和…

HarmonyOS应用开发——页面

我们将对于多页面以及更多有趣的功能展开叙述&#xff0c;这次我们对于 HarmonyOS 的很多有趣常用组件并引出一些其他概念以及解决方案、页面跳转传值、生命周期、启动模式&#xff08;UiAbility&#xff09;&#xff0c;样式的书写、状态管理以及动画等方面进行探讨 页面之间…

C++基础 -45- 类的静态数据成员

类的静态成员不包含在对象空间内 举例验证 定义普通变量和静态的变量 输出可知静态成员并没有占用类空间 静态数据成员的赋值&#xff08;必须类外赋值&#xff09; int base:: b 100;静态数据成员的访问&#xff08;不需要先定义对象&#xff09; int main() {cout <…

最新关于openai.APIConnectionError: Connection error.的解决方法

其实是和以前一样的处理方式&#xff0c;&#xff08;挂魔法&#xff09;修改代理&#xff0c;但是openai的源码改了&#xff0c;好多博客的方法不能用了。现在给一个新的修改方式&#xff0c;自己用的&#xff0c;发现可以。 1.找到pip下载的openai的Lib&#xff0c;找到_base…

揭秘AI魔法绘画:Stable Diffusion引领无限创意新纪元

文章目录 1. 无限的创意空间2. 高效的创作过程3. 个性化的艺术表达4. 跨界合作的可能性5. 艺术教育的革新6. 艺术市场的拓展 《AI魔法绘画&#xff1a;用Stable Diffusion挑战无限可能》编辑推荐内容简介作者简介精彩书评目录前言/序言本书读者对象学习建议获取方式 随着科技的…

SpringCloud微服务 【实用篇】| http客户端Feign

目录 一&#xff1a;http客户端Feign 1. Feign替代RestTemplate 2. 自定义配置 3. Feign性能优化 4. 最佳实践 前言 前些天突然发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家&#xff0c;感兴趣的同学可以…

开启三层交换机DHCP服务

二层交换机上不需要配置任何东西&#xff0c;只需要在pc机上开启dhcp服务&#xff0c;配置好LSW1后就可以自动获取到IP地址。 sys Enter system view, return user view with CtrlZ. [Huawei]sys sw1 [sw1]dhcp enable Info: The operation may take a few seconds. Please wai…

MES管理系统在生产计划排程中的应用与价值

随着制造业市场竞争的日益激烈和客户需求的多样化&#xff0c;传统的生产计划排程方式已经无法满足企业的需求。为了提升生产计划的效率和准确性&#xff0c;越来越多的企业开始引入MES管理系统这一先进的工具。那么&#xff0c;MES管理系统到底是什么&#xff0c;又是如何解决…

基于c++版本的数据结构改-python栈和队列思维总结

##栈部分-&#xff08;叠猫猫&#xff09; ##抽象数据类型栈的定义&#xff1a;是一种遵循先入后出的逻辑的线性数据结构。 换种方式去理解这种数据结构如果我们在一摞盘子中取到下面的盘子&#xff0c;我们首先要把最上面的盘子依次拿走&#xff0c;才可以继续拿下面的盘子&…

Nodejs+vue+ElementUi自动排课系统

使用自动排课系统分为管理员和学生、教师三个角色的权限子模块。 管理员所能使用的功能主要有&#xff1a;首页、个人中心、学生管理、教师管理、班级信息管理、专业信息管理、教室信息管理、课程信息管理、排课信息管理、系统管理等。 学生可以实现首页、个人中心、排课信息管…

uni-app 微信小程序之新增 添加小程序的交互

文章目录 1. 实现效果2. 提示组件 1. 实现效果 2. 提示组件 在 components 中新增 struggler-uniapp-add-tip 提示添加小程序 组件默认展示&#xff0c;通过点击将 SHOW_TIP 存储本地进行隐藏 <template><view><view class"uni-add-tips-box" v-if&…

【LeetCode】2629. 复合函数

复合函数 题目题解 题目 请你编写一个函数&#xff0c;它接收一个函数数组 [f1, f2, f3&#xff0c;…&#xff0c; fn] &#xff0c;并返回一个新的函数 fn &#xff0c;它是函数数组的 复合函数 。 [f(x)&#xff0c; g(x)&#xff0c; h(x)] 的 复合函数 为 fn(x) f(g(h(x…

深度学习在单线性回归方程中的应用--TensorFlow实战详解

深度学习在单线性回归方程中的应用–TensorFlow实战详解 文章目录 深度学习在单线性回归方程中的应用--TensorFlow实战详解1、人工智能<-->机器学习<-->深度学习2、线性回归方程3、TensorFlow实战解决单线性回归问题人工数据集生成构建模型训练模型定义损失函数定义…

bpftrace原理与使用方法

Bpftrace 概念和原理bpftrace安装bpftrace 语法结构bpftrace 变量内置变量自定义变量Map变量 内置函数Bpftrace操作案例文件系统磁盘进程内存 bpftrace是一种基于eBPF&#xff08;Extended Berkeley Packet Filter&#xff09;的跟踪工具&#xff0c;用于在Linux系统中进行动态…

金山终端安全系统V9.0 update_software_info_v2.php处SQL注入漏洞复现 [附POC]

文章目录 金山终端安全系统V9.0 update_software_info_v2.php处SQL注入漏洞复现 [附POC]0x01 前言0x02 漏洞描述0x03 影响版本0x04 漏洞环境0x05 漏洞复现1.访问漏洞环境2.构造POC3.复现 0x06 修复建议参考链接&#xff1a; 金山终端安全系统V9.0 update_software_info_v2.php处…

国产麒麟操作系统部署记录

前提&#xff1a;部署项目首先要安装各种软件&#xff0c;在内网环境下无法在线下载。 思路&#xff1a;首先部署一台能上网的系统&#xff0c;在此系统下只下载包&#xff0c;然后传到另一台内网系统下进行安装&#xff1b; 1、最开始yum未安装&#xff0c;因此需要先安装yu…

Leetcode每日一题学习训练——Python3版(到达首都的最少油耗)

版本说明 当前版本号[20231205]。 版本修改说明20231205初版 目录 文章目录 版本说明目录到达首都的最少油耗理解题目代码思路参考代码 原题可以点击此 2477. 到达首都的最少油耗 前去练习。 到达首都的最少油耗 ​ 给你一棵 n 个节点的树&#xff08;一个无向、连通、无环…

7nm项目之顶层规划——01数据导入

1.创建workspace 创建workspace后&#xff0c;在其目录下产生。 CORTEXA53.json文件是将有默认配置的文件master.json、有library的.config.json文件、tunes下CORTEXA53.tunes.json文件合并 注&#xff1a;tunes下的CORTEXA53.tunes.json文件可以覆盖一些master.json的设置…