选中点作为根节点能保证最小高度,因为中点分割使左右子树节点数最均衡,避免某侧多出一层;递归边界为left>right时返回nullptr,且需用new动态分配节点。

为什么选中点作为根节点才能保证最小高度
因为二叉搜索树的高度取决于左右子树的最大深度,而要让整棵树高度最小,必须让左右子树节点数尽可能均衡。对有序数组而言,每次取 mid = (left + right) / 2 对应的元素作根,能天然把剩余元素均分为左右两段——左段构左子树,右段构右子树。如果偏左或偏右取,某侧子树会多出一层,整体高度就上去了。
注意:C++ 中整数除法向零截断,(left + right) / 2 在不溢出前提下是安全的;但更健壮写法是 left + (right - left) / 2,避免 left + right 溢出(尤其当数组极大时)。
递归实现的关键边界与 nullptr 处理
递归终止条件不是 left == right,而是 left > right,此时返回 nullptr。漏掉这个判断会导致访问越界或无限递归。
- 输入空数组?传入
left = 0, right = -1,直接满足left > right,返回nullptr - 单元素?
left == right,构造一个节点,左右子指针自然为nullptr - 务必用
new TreeNode(nums[mid]),而非栈上临时对象——否则函数返回后节点就被销毁
完整可运行代码片段(含头文件与测试)
#include <vector>
#include <memory><p>struct TreeNode {
int val;
TreeNode <em>left;
TreeNode </em>right;
TreeNode() : val(0), left(nullptr), right(nullptr) {}
TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
TreeNode(int x, TreeNode <em>left, TreeNode </em>right) : val(x), left(left), right(right) {}
};</p>
<p>TreeNode* sortedArrayToBST(const std::vector<int>& nums) {
if (nums.empty()) return nullptr;</int></p>
<pre class="brush:php;toolbar:false;">auto build = [&](auto&& self, int left, int right) -> TreeNode* {
if (left > right) return nullptr;
int mid = left + (right - left) / 2;
TreeNode* root = new TreeNode(nums[mid]);
root->left = self(self, left, mid - 1);
root->right = self(self, mid + 1, right);
return root;
};
return build(build, 0, nums.size() - 1);
}
这里用了 C++17 的自捕获 lambda 实现尾递归风格,避免额外写一个私有辅助函数。若用传统方式,需声明 TreeNode* build(const std::vector<int>& nums, int left, int right)</int>。
LeetCode 提交时要注意内存管理
题目不要求手动释放内存,所以用 new 是允许的;但实际工程中应优先用 std::unique_ptr<treenode></treenode> 避免泄漏。LeetCode 的判题环境不析构你建的树,所以即使不 delete 也不会报错——但这不代表可以忽略所有权语义。
最容易被忽略的一点:数组索引是闭区间 [left, right],不是左闭右开。一旦写成 right 为开区间,mid 计算和递归调用边界全得跟着改,极易出错。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











