leetcode108.将有序数组转换为二叉搜索树(递归+迭代)

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

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

1.递归法:

解题步骤:
为了使得得到的树是平衡二叉搜索树,取数组nums的中位数为根节点,以中位数为分割点切分左右子树,这样能保证做右子树的高度差达到最小化;
左右子树重复前面的操作:取中位数为根节点,以中位数为分割点切分左右子树;
当下标left > right时递归调用结束,也意味着数组中没有节点供我们使用了。

注意事项:
一定要保持从始至终下标要么是左闭右闭区间,要么就是左闭右开。我这里选择左闭右闭。

中位数如何取?
可以直接取两下标的平均:middle = (left + right) / 2
对于奇数个下标的数组:可以直接求出中间下标;
对于偶数个下标的数组:middle不是中间下标,而是中间位置左边的数字下标,这不会影响后续结果。

小优化:
避免栈溢出的风险,可以将middle = (left + right) / 2优化成middle = (right - left) / 2 + left,或者middle = (right - left) >> 1 + left

最终代码如下:

TreeNode* BuildBST(vector<int>& nums, int left, int right)
{
    if(left > right) return nullptr;

    // 定义中间位置作为根节点
    int middle = ((right - left) >> 1) + left;
    TreeNode* newnode = new TreeNode(nums[middle]);
    // 中间节点分割左右区间
    newnode->left = BuildBST(nums, left, middle - 1);
    newnode->right = BuildBST(nums, middle + 1, right);
    return newnode;
}
TreeNode* sortedArrayToBST(vector<int>& nums) {
    return BuildBST(nums, 0, nums.size() - 1);
}

复杂度分析

时间复杂度: O(N),其中 N 是数组的长度。每个数字都要访问一次。

空间复杂度: O(logN),其中 N 是数组的长度。空间复杂度取决于递归栈的深度,递归栈的深度是 O(log⁡N),也就是整个二叉树的高度。
在这里插入图片描述

2.迭代法:

建立三个队列:
qNode队列用于存放遍历的节点,节点的初始化交给另外两个队列完成;
qLeft队列用于存放区间的左边界下标;
qRight队列用于存放区间的右边界下标;
当取出左右边界下标,即可计算出middle,也就能初始化qNode里的节点了。

TreeNode* sortedArrayToBST(vector<int>& nums) {
	if(nums.size() == 0) return nullptr;
	// qNode用于存放遍历的节点
	TreeNode* root = new TreeNode(0);
	queue<TreeNode*> qNode; qNode.push(root);
	// qLeft用于存放左边界下标
	queue<int> qLeft; qLeft.push(0);
	// qRight用于存放右边界下标
	queue<int> qRight; qRight.push(nums.size() - 1);
	while(!qNode.empty())
	{
	    TreeNode* root = qNode.front(); qNode.pop();
	    int left = qLeft.front(); qLeft.pop();
	    int right = qRight.front(); qRight.pop();
	    // 得到中节点下标
	    int middle = ((right - left) >> 1) + left;
	    
	    root->val = nums[middle]; // 将根节点的值改为中间节点的值
	
	    // 划分左区间
	    if(left <= middle - 1)
	    {
	        root->left = new TreeNode(0); // 创建新节点连接在root->left
	        qNode.push(root->left);
	        qLeft.push(left);
	        qRight.push(middle - 1);
	    }
	
	    // 划分右区间
	    if(middle + 1 <= right)
	    {
	        root->right = new TreeNode(0); // 创建新节点连接在root->right
	        qNode.push(root->right);
	        qLeft.push(middle + 1);
	        qRight.push(right);
	    }
	}
	return root;
}
  • 6
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值