算法力扣刷题记录 六十一【108.将有序数组转换为二叉搜索树】

前言

本文是二叉树篇刷题教程中的倒数第二道。加油。继续。
记录 六十一【108.将有序数组转换为二叉搜索树】


一、题目阅读

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

示例 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,null,3] 和 [3,1] 都是高度平衡二叉搜索树。

提示:

1 <= nums.length <= 10^4
-10^4 <= nums[i] <= 10^4
nums 按 严格递增 顺序排列

二、尝试实现

思路

  1. 先理解题目:把输入的一个有序递增数组转换成平衡二叉搜索树。平衡:任何节点的左右子树高度差不超过1;二叉搜索树:节点大小关系满足左子树内节点值< 中间节点 < 右子树内节点值。感觉好复杂,再想想
  2. 让构建一个二叉树:记录 五十【106.从中序与后序遍历序列构造二叉树】和【105.从前序与中序遍历序列构造二叉树】学过如此构造二叉树,是通过中间节点的位置去划分数组,直到数组中某一部分是左子树,哪一部分是右子树。这里也需要找中间节点 ,这样递归实现就可以cur->left和cur->right。
  3. 只给了一个数组,怎么确定中间节点呢?但是题目说平衡:把数组正中间的值当作中间节点,均分输入数组nums,左半边小于中间节点,右半边大于中间节点(二叉搜索树get);而且重复操作构建左右子树,每个节点的左右子树节点个数一样,应该可以满足平衡。思路有了,开始实现:
  4. 递归函数参数:输入的nums;
  5. 递归函数返回值:子树的根节点TreeNode*。向上一层返回创建的子树,在上面用left或者right接住返回值(很多次见到)。
  6. 递归函数终止条件:nums空——说明没有孩子,return nullptr。
  7. 递归函数逻辑:
  • 找到传入数组正中间的元素,新建根节点:nums[nums.size() /2];
  • 左子树=nums平分的前半段;
  • 右子树=nums平分的后半段。
  1. 如下图,结合文字理解。
    在这里插入图片描述

代码实现

以下代码实现中几个点:

  1. 因为想借助给的主函数实现递归,所以没去定义一个新函数。主函数只有一个参数nums,所以递归的时候,其实是建了新数组,开辟空间。不是用下标去控制原来的那一个数组
  2. 传递区间的时候,遵循左闭右开的区间。因为vector构造函数就是左闭右开。
class Solution {
public:
    TreeNode* sortedArrayToBST(vector<int>& nums) {
        //终止条件
        if(nums.size() == 0) return nullptr;

        //中间节点,用nums的正中间的值作为父节点。
        TreeNode* cur = new TreeNode(nums[nums.size()/2]);
        //构建左子树
        vector<int> leftsub(nums.begin(),nums.begin()+nums.size()/2 );//左闭右开
        cur->left = sortedArrayToBST(leftsub);
        //构建右子树
        vector<int> rightsub(nums.begin()+nums.size()/2+1,nums.end());
        cur->right = sortedArrayToBST(rightsub);

        return cur;
    }
};

三、参考学习

参考学习链接

学习内容

  1. 思路一致。
  2. 对比参考代码【递归法】:参考给的是下标控制同一个数组,没有额外开辟空间;同时传递区间使用左闭右闭。
  3. 迭代法:用循环模拟递归的过程。参考代码:使用了三个队列:一个队列放子树的根节点;一个队列放该节点对应的区间左下标;一个队列放该节点对应的区间右下标。可以看成是层序遍历的顺序去构建。

总结

记录 五十【106.从中序与后序遍历序列构造二叉树】和【105.从前序与中序遍历序列构造二叉树】同思路,用中间节点切分数组即可。保持循环不变量。

  • 15
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值