「这是我参与11月更文挑战的第21天,活动详情查看:2021最后一次更文挑战」
108. 将有序数组转换为二叉搜索树
题目描述
给你一个整数数组 nums ,其中元素已经按 升序 排列,请你将其转换为一棵 高度平衡 二叉搜索树。
高度平衡 二叉树是一棵满足「每个节点的左右两个子树的高度差的绝对值不超过 1 」的二叉树。
示例 1:
输入: nums = [-10,-3,0,5,9]
输出: [0,-3,9,-10,null,5]
解释: [0,-10,5,null,-3,null,9] 也将被视为正确答案:
示例 2:
输入: nums = [1,3]
输出: [3,1]
解释: [1,3] 和 [3,1] 都是高度平衡二叉搜索树。
解析
递归法
/**
* @brief 递归法
* 递归三部曲:
* 1、确定递归函数的参数与返回值
* 使用递归函数的返回值来构造节点的左右孩子
* 参数:传入的数组nums,左下标 left , 右下标 right。
* TreeNode *traversal(vector<int> &nums , int left, int right)
* 2、确定递归终止条件
* 当下标值 left > right 时就是空节点了
* if(left>right) return nullptr;
* 3、确定单层循环的逻辑
* (1)取数组元素的中间位置, int mid = (left+right) / 2
* 但是若left和right都是最大int ,那么操作就会越界,
* 所以中间元素的位置可以由:int mid = left+((right-left) / 2)来获得。
* 对于int mid = left + ((right-left)/2); 这种写法,当数组为偶数时,中间位置有两个元素,取左边的
* (2)取到中间位置的元素后,构造节点 : TreeNode *root = new TreeNode(nums[mid]) ;
* root的左孩子: root->left = traversal(nums,left,mid-1);
* root的右孩子: root->right = traversal(nums,mid+1,right);
* (此处体现出返回值的作用)
* 最后返回root .
*/
代码
class Solution
{
public:
TreeNode *sortedArrayToBST(vector<int> &nums)
{
int size = nums.size();
// 数组为空,直接返回空
if (size == 0)
{
return nullptr;
}
return traversal(nums, 0, size - 1);
}
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;
}
};
迭代法
/**
* @brief 迭代法
* 使用三个队列来实现
* 1、队列1 存放遍历的节点
* 2、队列2 存放左区间下标
* 3、队列3 存放右区间下标
*
* 迭代更新三个队列的同时创建二叉树
*
*/
代码
class Solution
{
public:
TreeNode *sortedArrayToBST(vector<int> &nums)
{
int size = nums.size();
if (size == 0)
{
return nullptr;
}
// 存放遍历的节点
queue<TreeNode *> q_nodes;
// 存放左区间的下标
queue<int> q_left;
// 存放右区间的下标
queue<int> q_right;
// 初始根节点
TreeNode *root = new TreeNode(0);
q_nodes.push(root);
q_left.push(0);
q_right.push(size - 1);
while (!q_nodes.empty())
{
TreeNode *node = q_nodes.front();
q_nodes.pop();
int left = q_left.front();
q_left.pop();
int right = q_right.front();
q_right.pop();
// 取数组中间的索引
int mid = left + ((right - left) / 2);
// 数组中间的元素
node->val = nums[mid];
// 左区间
if (left <= mid - 1)
{
node->left = new TreeNode(0);
q_nodes.push(node->left);
q_left.push(left);
q_right.push(mid - 1);
}
// 右区间
if (right >= mid + 1)
{
node->right = new TreeNode(0);
q_nodes.push(node->right);
q_left.push(mid + 1);
q_right.push(right);
}
}
return root;
}
};