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

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

一、题目

给你一个整数数组 nums ,其中元素已经按 升序 排列,请你将其转换为一棵 高度平衡 二叉搜索树。

高度平衡 二叉树是一棵满足「每个节点的左右两个子树的高度差的绝对值不超过 1 」的二叉树。

示例 1:

img

输入:nums = [-10,-3,0,5,9]
输出:[0,-3,9,-10,null,5]
解释:[0,-10,5,null,-3,null,9] 也将被视为正确答案:

示例 2:

img

输入:nums = [1,3]
输出:[3,1]
解释:[1,null,3] 和 [3,1] 都是高度平衡二叉搜索树。

提示:

  • 1 <= nums.length <= 104
  • -104 <= nums[i] <= 104
  • nums严格递增 顺序排列

二、题解

方法一:递归

我们知道平衡二叉搜索树的特点是每个节点的左子树和右子树的高度差不超过1,因此我们尽可能要让节点两端的元素个数相近。

算法思路:

  1. 首先,我们要找到一个合适的根节点。由于给定的数组是有序的,我们可以选择中间位置的元素作为根节点,这样可以保证左右子树的元素数量相差不大,从而有助于维持平衡性质。

  2. 在选择了根节点之后,我们将数组分成两部分:左子数组和右子数组。左子数组中的元素都小于根节点,右子数组中的元素都大于根节点。

  3. 然后,我们递归地对左子数组和右子数组进行相同的操作,分别构建左子树和右子树。这样就能保证左右子树的高度差不超过1。

  4. 最后,将根节点与构建好的左右子树连接起来,形成一棵完整的平衡二叉搜索树。

具体实现:

class Solution {
public:
    TreeNode* sortedArrayToBST(vector<int>& nums) {
        if(nums.size() == 0) return nullptr; // 空数组直接返回空指针(终止条件)
        int size = nums.size();
        int middle = size/2; // 找到中间位置的索引
        TreeNode *root = new TreeNode(nums[middle]); // 创建根节点
        vector<int> vecL(nums.begin(),nums.begin()+middle); // 左子数组
        vector<int> vecR(nums.begin()+middle+1, nums.end()); // 右子数组
        root->left = sortedArrayToBST(vecL); // 递归构建左子树
        root->right = sortedArrayToBST(vecR); // 递归构建右子树
        return root; // 返回根节点
    }
};

算法分析:

  • 时间复杂度:每个元素都会被遍历一次,因此总的时间复杂度为 O(n),其中 n 是数组中的元素数量。
  • 空间复杂度:每次递归都会创建新的左右子数组,因此递归的最大深度是 log(n),每层需要的空间为 O(n),所以总的空间复杂度为 O(nlogn)。
方法二:迭代

以下是代码的思路:

  1. 首先,检查给定的有序数组是否为空,如果为空,则直接返回空指针,表示空树。

  2. 创建一个根节点 root,暂时将其值设为0,作为占位值。然后创建三个队列:nodeQue 用于存储待处理的节点,leftQue 用于存储每个节点对应的左区间下标,rightQue 用于存储每个节点对应的右区间下标。

  3. 将根节点 root、左区间下标0和右区间下标 nums.size() - 1 分别入队列。

  4. 进入迭代循环,从队列中取出一个待处理的节点 curNode,同时获取它对应的左区间下标 left 和右区间下标 right,计算当前区间的中间位置 mid

  5. 将中间位置 mid 对应的元素值赋给当前节点 curNode->val,此时树的结构仍未构建。

  6. 如果左区间 left 小于等于 mid - 1,则创建左子节点,并将其入队列。更新 leftQuerightQue 分别为 leftmid - 1

  7. 如果右区间 right 大于等于 mid + 1,则创建右子节点,并将其入队列。更新 leftQuemid + 1,并维持 rightQue 不变。

  8. 重复以上步骤,直到队列为空,此时所有的节点都已经处理完毕,构建的二叉搜索树也完成。

  9. 返回根节点 root,即完成了整个构建过程。

class Solution {
public:
    TreeNode* sortedArrayToBST(vector<int>& nums) {
        if (nums.empty()) {
            return nullptr;
        }

        TreeNode* root = new TreeNode(0);   // 初始根节点,暂时使用0作为占位值
        queue<TreeNode*> nodeQue;           // 存储待处理的节点
        queue<int> leftQue;                 // 存储当前节点对应的左区间下标
        queue<int> rightQue;                // 存储当前节点对应的右区间下标
        nodeQue.push(root);                 // 根节点入队列
        leftQue.push(0);                    // 0为初始左区间下标
        rightQue.push(nums.size() - 1);     // nums.size() - 1为初始右区间下标

        while (!nodeQue.empty()) {
            TreeNode* curNode = nodeQue.front(); nodeQue.pop();// 当前待处理节点
            int left = leftQue.front(); leftQue.pop();    // 当前节点对应的左区间下标
            int right = rightQue.front(); rightQue.pop(); // 当前节点对应的右区间下标
            int mid = left + (right - left) / 2;  // 计算当前区间的中间位置

            curNode->val = nums[mid];   // 将中间位置元素赋值给当前节点,此时树的结构仍未构建

            if (left <= mid - 1) {  // 如果左区间仍有元素可用,创建左子节点
                curNode->left = new TreeNode(0);  
                nodeQue.push(curNode->left);  // 将左子节点加入待处理队列
                leftQue.push(left);   // 更新左区间下标
                rightQue.push(mid - 1); // 更新右区间下标
            }

            if (right >= mid + 1) { // 如果右区间仍有元素可用,创建右子节点
                curNode->right = new TreeNode(0); 
                nodeQue.push(curNode->right); // 将右子节点加入待处理队列
                leftQue.push(mid + 1); // 更新左区间下标
                rightQue.push(right);  // 更新右区间下标
            }
        }
        return root; 
    }
};

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

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

相关文章

Android相机-架构

引言&#xff1a; 主要是针对CameraAPI v2 HAL3的架构对Android相机系统进行梳理。 相机架构 App和FrameWork Camera API v2位于&#xff1a; packages/apps/Camer2 frameworks/ex/camera2 应用框架级别&#xff0c;使用Camera2 API与相机的硬件进行交互。通过调用Binder接口…

无涯教程-PHP - 移除的扩展

以下扩展已从PHP 7开始删除- eregmssqlmysqlsybase_ct 以下SAPI已从PHP 7开始删除- aolserverapacheapache_hooksapache2filtercaudiumcontinuityisapimilternsapiphttpdpi3webroxenthttpdtuxwebjames PHP - 移除的扩展 - 无涯教程网无涯教程网提供以下扩展已从PHP 7开始删除…

PostgreSQL基本操作总结

安装按PostgreSQL数据库后&#xff0c;会默认创建用户postgres和数据库postgres&#xff0c;这个用户是超级用户&#xff0c;权限最高&#xff0c;可以创建其他用户和权限&#xff0c;在实际开发过程中&#xff0c;会新创建用户和业务数据库&#xff0c;本文主要介绍用户权限和…

【LeetCode】167. 两数之和 II - 输入有序数组 - 双指针

目录标题 2023-8-23 09:25:08 2023-8-23 09:25:08 自己写的不是常量级的额外空间&#xff0c;但是写出来了&#xff0c;记录一下。 下次写的时候&#xff0c;请用双指针。 &#xff08;其实我想了想一想&#xff0c;双指针就没感觉出来&#xff1a;因为我只想到双指针两个都…

Ompl初探

在/ompl-1.x.0/build/Release/bin下有很多生成的demo可执行文件 在终端执行 ./demo_Point2DPlanning 测试程序 #include <ompl/base/SpaceInformation.h> #include <ompl/base/spaces/SE3StateSpace.h> #include <ompl/base/StateSpace.h> #include <o…

java八股文面试[java基础]——接口和抽象类的区别

知识来源&#xff1a; 【基础】接口和抽象类_哔哩哔哩_bilibili 【2023年面试】Java中抽象类和接口有什么区别_哔哩哔哩_bilibili 【23版面试突击】抽象类和接口的区别&#xff0c;类可以继承多个类么&#xff0c;接口可以继承多个接口么,类可以实现多个接口么&#xff1f;_…

langchain ChatGPT AI私有知识库

企业知识库 原理就是把文档变为向量数据库&#xff0c;然后搜索向量数据库&#xff0c;把相似的数据和问题作为prompt&#xff0c; 输入到大模型&#xff0c;再利用GPT强大的自然语言处理、推理和分析等方面的能力将答案返回给用户 什么是langchain? langchain是一个强大的…

Docker 微服务实战

1. 通过IDEA新建一个普通微服务模块 1.1 建Module docker_boot 1.2 改写pom <?xml version"1.0" encoding"UTF-8"?><project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance&…

uview2.0自定义tabbar

tabbar组件 <template><u-tabbar :value"tab" change"changeTab" :fixed"true" :border"true" :placeholder"true":safeAreaInsetBottom"true"><u-tabbar-item text"消息" icon"c…

Mac OS 中JDK 环境(jdk 1.8.0_831)安装配置、环境变量配置及卸载操作

前言&#xff1a; 摊牌了&#xff0c;本来就有点喜新厌旧的我&#xff0c;特意把系统和开发环境都拉到比较高&#xff0c;想试验一下兼容性和某些新特性&#xff0c;探索了一下新大陆&#xff0c;也见识了各种光怪陆离的妖魔鬼怪。 因为要着手云平台项目的重构改版和新系统的架…

Vue+Axios搭建二次元动态登录页面(mp4视频格式)

最近想做一个前端登录页面&#xff0c;背景好看的&#xff0c;格式中规中矩的&#xff0c;这么难&#xff1f;我自己创一个吧&#xff01; 效果图如下&#xff1a; 源码可以参考我的github&#xff0c;复制源码即可用&#xff1a;gym02/loginPage_Vue: 使用VueAxios搭建的动态…

2022年30m全国逐年土地覆被数据

1.研究背景 2023年8月,武汉大学杨杰和黄昕教授团队向公众更新发布了CLCD 2022年全国土地覆数据(V1.0.2)。而CLCD 2021年全国土地覆数据(V1.0.1)也是在去年8月向公众更新发布。 中国在过去几十年中经济和人口迅速发展,土地覆盖随之发生巨大变化,因此迫切需要对其进行连续…

将AI融入CG特效工作流;对谈Dify创始人张路宇;关于Llama 2的一切资源;普林斯顿LLM高阶课程;LLM当前的10大挑战 | ShowMeAI日报

&#x1f440;日报&周刊合集 | &#x1f3a1;生产力工具与行业应用大全 | &#x1f9e1; 点赞关注评论拜托啦&#xff01; &#x1f916; 将AI融入CG特效工作流&#xff0c;体验极致的效率提升 BV1pP411r7HY 这是 B站UP主 特效小哥studio 和 拓星研究所 联合投稿的一个AI特…

Unity shader 入门之渲染管线一、总览

如下示意图 应用阶段(ApplicationStage)&#xff1a;准备场景信息&#xff08;视景体&#xff0c;摄像机参数&#xff09;、粗粒度剔除、定义每个模型的渲染命令&#xff08;材质&#xff0c;shader&#xff09;——由开发者定义&#xff0c;不做讨论。几何阶段(GemetryStage)&…

商城-学习整理-集群-K8S(二十三)

目录 一、k8s 集群部署1、k8s 快速入门1&#xff09;、简介2&#xff09;、架构1、整体主从方式2、Master 节点架构3、Node 节点架构 3&#xff09;、概念4&#xff09;、快速体验1、安装 minikube2、体验 nginx 部署升级 5&#xff09;、流程叙述 2、k8s 集群安装1、kubeadm2、…

matlab中判断数据的奇偶性(mod函数、rem函数)

用Matlab判断一个数是偶数还是奇数 1、mod函数 X 25;%要判断的数 if mod(X,2)1disp(奇数);%奇数 elsedisp(偶数);%偶数 end结果 2、rem函数 n25; if rem(n,2)0display(偶数); elsedisplay(奇数); end结果

neo4j

UNWIND 将列表里的值展开 CREATE (N0:Person {name: Anders}) CREATE (N1:Person {name: Becky}) CREATE (N2:Person {name: Cesar}) CREATE (N3:Person {name: Dilshad}) CREATE (N4:Person {name: George}) CREATE (N5:Person {name: Filipa})CREATE (N0)-[:KNOWS]->(N3)…

Nevron Open Vision for .NET Crack

Nevron Open Vision for .NET Crack NET Vision是一个用于生成具有数据可视化功能的强大数据表示应用程序的包。该套件具有用于.NET的Nevron Chart、用于.NET的Nevron Diagram和用于.NET的Nevron User Interface。精心设计的对象模型、许多功能和卓越的演示使复杂数据的可视化变…

【Terraform学习】使用 Terraform 将 EC2 实例作为 Web 服务器启动(Terraform-AWS最佳实战学习)

使用 Terraform 将 EC2 实例作为 Web 服务器启动 实验步骤 前提条件 安装 Terraform&#xff1a; 地址 下载仓库代码模版 本实验代码位于 task_ec2 文件夹中。 变量文件 variables.tf 在上面的代码中&#xff0c;您将声明&#xff0c;aws_access_key&#xff0c;aws_secr…

基于YOLOv8模型和Caltech数据集的行人检测系统(PyTorch+Pyside6+YOLOv8模型)

摘要 基于YOLOv8模型和Caltech数据集的行人检测系统可用于日常生活中检测与定位行人&#xff0c;利用深度学习算法可实现图片、视频、摄像头等方式的行人目标检测&#xff0c;另外本系统还支持图片、视频等格式的结果可视化与结果导出。本系统采用YOLOv8目标检测算法训练数据集…