news 2026/5/21 21:37:29

今日算法(构造二叉搜索树)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
今日算法(构造二叉搜索树)

题目描述

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

平衡二叉搜索树

  • 左右两个子树的高度差的绝对值不超过 1
  • 每个节点的左右子树都是平衡二叉树
  • 二叉搜索树的中序遍历结果是一个升序序列,正好和输入数组的顺序一致

核心思路:分治递归 + 中序遍历还原

要构造一棵平衡的 BST,核心是每次选择数组的中间元素作为根节点,这样可以保证左右子树的节点数量尽可能相等,从而天然满足平衡条件。

分治逻辑

  1. 递归终止条件:当数组区间为空(左边界 > 右边界)时,返回nullptr
  2. 选择根节点:取数组中间位置的元素作为当前子树的根节点
  3. 递归构造左右子树
    • 左子树:使用数组[left, mid-1]区间的元素构造
    • 右子树:使用数组[mid+1, right]区间的元素构造
  4. 返回根节点:左右子树构造完成后,返回当前根节点

完整代码实现(C++)

cpp

/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode() : val(0), left(nullptr), right(nullptr) {} * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} * }; */ class Solution { public: TreeNode* sortedArrayToBST(vector<int>& nums) { // 调用分治函数,初始区间为整个数组 [0, nums.size()-1] return build(nums, 0, nums.size() - 1); } private: // 分治递归函数:在区间 [left, right] 内构造平衡BST TreeNode* build(vector<int>& nums, int left, int right) { // 1. 递归终止条件:区间为空,返回空节点 if (left > right) return nullptr; // 2. 选择中间元素作为根节点(避免溢出,用 left + (right-left)/2 代替 (left+right)/2) int mid = left + (right - left) / 2; TreeNode* root = new TreeNode(nums[mid]); // 3. 递归构造左子树:区间 [left, mid-1] root->left = build(nums, left, mid - 1); // 4. 递归构造右子树:区间 [mid+1, right] root->right = build(nums, mid + 1, right); // 5. 返回当前子树的根节点 return root; } };

详细执行流程解析

我们以示例nums = [-10,-3,0,5,9]为例,模拟递归执行过程:

1. 第一次递归(根节点构造)

  • 区间:[0, 4](对应数组全部元素)
  • 中间位置mid = 0 + (4-0)/2 = 2,对应元素nums[2] = 0
  • 构造根节点0,左子树区间[0,1],右子树区间[3,4]

2. 构造左子树(区间[0,1]

  • 中间位置mid = 0 + (1-0)/2 = 0,对应元素nums[0] = -10
  • 构造节点-10,左子树区间[0,-1](空,返回nullptr),右子树区间[1,1]
  • 递归构造右子树(区间[1,1]):
    • 中间位置mid=1,对应元素nums[1] = -3
    • 构造节点-3,左右区间均为空,返回节点-3
  • 节点-10的右子树为-3,返回节点-10

3. 构造右子树(区间[3,4]

  • 中间位置mid = 3 + (4-3)/2 = 3,对应元素nums[3] = 5
  • 构造节点5,左子树区间[3,2](空,返回nullptr),右子树区间[4,4]
  • 递归构造右子树(区间[4,4]):
    • 中间位置mid=4,对应元素nums[4] = 9
    • 构造节点9,左右区间均为空,返回节点9
  • 节点5的右子树为9,返回节点5

4. 最终结果

根节点0的左子树为-10,右子树为5,形成平衡二叉搜索树,和示例输出一致。


关键细节与易错点

  1. 中间位置的计算方式推荐使用mid = left + (right-left)/2,而不是(left+right)/2。当leftright很大时,(left+right)可能会溢出导致整数越界,前者可以有效避免这个问题。

  2. 平衡条件的保证每次选择中间元素作为根节点,会将数组分成两个长度差不超过 1 的子区间,因此左右子树的高度差永远不会超过 1,天然满足平衡 BST 的要求。

  3. 中序遍历的一致性构造的 BST 的中序遍历结果,和原数组的顺序完全一致,这是 BST 的核心性质,也是分治递归的基础。

  4. 节点的创建与内存管理题目只要求返回根节点,因此不需要额外处理内存释放。在实际工程中,需要手动释放节点避免内存泄漏。


复杂度分析

  • 时间复杂度:(O(n)),其中 n 为数组的长度。每个元素都会被访问一次,创建一个节点。
  • 空间复杂度:(O(log n)),其中 n 为数组的长度。递归调用栈的深度等于树的高度,由于是平衡树,高度为 (log n),最坏情况下(数组长度为 1)为 (O(1))。

拓展:迭代版实现(可选)

如果不想使用递归,也可以用迭代的方式(队列模拟递归栈)实现,核心逻辑和递归一致:

cpp

class Solution { public: TreeNode* sortedArrayToBST(vector<int>& nums) { if (nums.empty()) return nullptr; // 队列中存储:当前节点、区间左边界、区间右边界 queue<tuple<TreeNode*, int, int>> q; // 1. 创建根节点 int mid = nums.size() / 2; TreeNode* root = new TreeNode(nums[mid]); q.emplace(root, 0, nums.size() - 1); while (!q.empty()) { auto [node, left, right] = q.front(); q.pop(); int curMid = left + (right - left) / 2; // 构造左子树 if (left <= curMid - 1) { int leftMid = left + (curMid - 1 - left) / 2; TreeNode* leftChild = new TreeNode(nums[leftMid]); node->left = leftChild; q.emplace(leftChild, left, curMid - 1); } // 构造右子树 if (curMid + 1 <= right) { int rightMid = curMid + 1 + (right - (curMid + 1)) / 2; TreeNode* rightChild = new TreeNode(nums[rightMid]); node->right = rightChild; q.emplace(rightChild, curMid + 1, right); } } return root; } };

总结

将有序数组转换为平衡二叉搜索树,核心就是利用分治思想,每次选择中间元素作为根节点,保证左右子树的节点数量尽可能均衡,从而构造出平衡的 BST。这种方法时间复杂度为线性,空间复杂度为对数级,是最优解之一。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/21 21:36:45

腾讯版Claude Design来了:多人实时同屏审设计稿,一键转代码直通IDE

闻乐 发自 凹非寺量子位 | 公众号 QbitAIClaude Design前脚刚把设计圈炸完&#xff0c;腾讯又公测了一个Ardot——AI设计智能体平台&#xff0c;一句话生成可编辑UI设计稿、Figma文件零成本导入、一键转代码直通IDE、多人在线评审……短短一个月&#xff0c;Adobe、Figma那边估…

作者头像 李华
网站建设 2026/5/21 21:35:19

上海AI实验室发布WildClawBench:AI智能体究竟能走多远?

这项由上海人工智能实验室联合香港中文大学、复旦大学、中国科学技术大学、上海交通大学、清华大学、浙江大学及南洋理工大学等多所顶尖机构共同完成的研究&#xff0c;于2026年5月11日以预印本形式发布&#xff0c;论文编号为arXiv:2605.10912v1。感兴趣的读者可通过该编号在a…

作者头像 李华
网站建设 2026/5/21 21:31:17

2026网盘怎么选?从同步速度、数据安全到协作体验:坚果云为何更稳

有人图免费空间大&#xff0c;有人要下载别限速&#xff0c;有人最在意数据安全合规&#xff0c;还有人只求“跨设备同步别掉链子”。到2026年&#xff0c;网盘早就不是“谁送得多谁就赢”&#xff0c;而是谁能把同步稳定、权限协作、合规安全这三件事长期做好。 先把话说在前…

作者头像 李华
网站建设 2026/5/21 21:30:15

告别EEPROM!用STM32F4给ADI A2B音频总线脱机启动(保姆级图文教程)

基于STM32F4的ADI A2B音频总线脱机启动全流程解析 在嵌入式音频系统开发中&#xff0c;ADI的A2B&#xff08;Automotive Audio Bus&#xff09;技术因其高带宽、低延迟和简化布线的特性&#xff0c;逐渐成为汽车音频架构的首选方案。传统开发流程依赖PC连接和EEPROM存储配置&am…

作者头像 李华