《程序员面试金典(第6版)》面试题 04.02. 最小高度树

题目描述

给定一个有序整数数组,元素各不相同且按升序排列,编写一个算法,创建一棵高度最小的二叉搜索树。

示例:
给定有序数组: [-10,-3,0,5,9],

一个可能的答案是:[0,-3,9,-10,null,5],它可以表示下面这个高度平衡二叉搜索树:

      0 
     / \ 
   -3   9 
   /   / 
 -10  5 

解题思路与代码

做这道题,需要你对二叉树这种数据结构有基本的了解,知道什么叫做二叉搜索树。并且知道基本的递归函数怎么写,递归函数的三要素是什么。

这道题给了我们一个有序的数组,让我们把它变成一颗二叉搜索树,且这个二叉搜索树的高度要最小。首先我们知道二叉搜索树的性质,那就是左边节点小于中间节点,中间节点小于右边节点。它要求高度最小,我们就把数组最中间的那个元素拿出来做中间节点,那出来的二叉树的高度必然是最小的。(自己随便画一下就知道)

中序遍历法(中间或中间靠左边节点做中间节点)

这个方法要求我们选取数组最中间,或最中间偏左的元素取出来做中间节点。

首先,我们要自己去写一个新的递归函数。因为原函数只能传递一个参数,我们施展不开手脚。新的递归函数的返回类型还是TreeNode*类型,我们需要传入三个参数,分别一个是一直存在的数组,一个是左起始点,一个是右结束点。
然后就是基本的逻辑判断了。

需要注意的是,数组的下标。不要越界了。这个是这道题唯一需要注意的点。
请注意这一行代码:int mid = (end + begin) / 2 ;注意这里一定是end + begin,而不是end - begin。这是阿宋以前经常犯下的错误,希望你们以后不要再犯。

具体的代码如下:

class Solution {
public:
    TreeNode* sortedArrayToBST(vector<int>& nums) {
        return inorderTraversal(nums,0,nums.size()-1);
    }

    TreeNode* inorderTraversal(vector<int>& nums,int begin,int end){
        if(begin > end) return nullptr;
        int mid = (end + begin) / 2 ;
        TreeNode* head = new TreeNode(nums[mid]);
        head->left = inorderTraversal(nums,begin,mid-1);
        head->right = inorderTraversal(nums,mid+1,end);
        return head;
    }
};
复杂度分析

时间复杂度:

  • O(n),其中n等于数组nums中的元素数量。因为我们的代码采用递归的方式去编写,在每次递归的时候都去查找一个区间中的mid值,并创建占用常数时间的TreeNode节点。然后递归调用左边的子范围和右边的子范围。

空间复杂度:

  • O(logn),由于我们每次递归调用区间长度都会缩小到原来的一半,所以我们需要递归log2^n 次才能将区间变空,所以就消耗了O(logn)的堆栈空间,所以空间复杂度就是O(logn)。

总结

这道题不是什么难题,只要你基础知识扎实,分分钟就做出来。如果基础不扎实也没关系,努力夯实基础就行。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阿宋同学

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值