代码随想录二刷 |二叉树 | 将有序数组转换为二叉搜索树
- 题目描述
- 解题思路
- 代码实现
题目描述
109.将有序数组转换为二叉搜索树
将一个按照升序排列的有序数组,转换为一棵高度平衡二叉搜索树。
本题中,一个高度平衡二叉树是指一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1。
示例:
解题思路
寻找分割点,即数组中间位置的节点。
当数组元素为偶数个时,中间节点取哪一个都可以,只是构成了不同的平衡二叉树。
递归三部曲
-
确定递归函数的参数和返回值
本题要构造二叉树,依然用递归函数的返回值来构造中节点的左右孩子。再来看参数,首先是传入数组,然后就是左下标left和右下标right,在构造二叉树的时候尽量不要重新定义左右区间数组,而是用下标来操作原数组。
返回值:TreeNode*
参数: nums, left, right代码如下:
// 左闭右闭区间 TreeNode* traversal(vector<int>& nums, int left, int right)
-
确定递归函数的终止条件
因为定义的是左闭右闭区间,所以当 left > right时,就遇到空节点了。if (left > right) return nullptr;
-
确定单层递归的逻辑
首先取数组中间元素的位置,int mid = (left + right) / 2;
这么写其实有一个问题,就是数值越界,例如left和right都是最大int,这么操作就越界了,在二分法 (opens new window)中尤其需要注意!
所以可以这么写:
int mid = left + ((right - left) / 2);
但本题leetcode的测试数据并不会越界,所以怎么写都可以。但需要有这个意识!
取了中间位置,就开始以中间位置的元素构造节点,代码:
TreeNode* root = new TreeNode(nums[mid]);
接着划分区间,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;
代码实现
class Solution {
private: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;}
public:TreeNode* sortedArrayToBST(vector<int>& nums) {TreeNode* root = traversal(nums, 0, nums.size() - 1);return root;}
};