【LeetCode二叉树#19】有序数组转换为二叉搜索树(构造二叉树)
将有序数组转换为二叉搜索树
将一个按照升序排列的有序数组,转换为一棵高度平衡二叉搜索树。
本题中,一个高度平衡二叉树是指一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1。
示例:

思路
本题还是考察的构建二叉树
之前也有做过类似的题目,基本上来说,构造二叉树就是按照题目规则找根节点,然后调用递归不断构造出其左右子树即可
那么,本题的规则是什么?
题目要求我们将升序排列的有序数组,转换为一棵高度平衡二叉搜索树
因此,可以用数组的中间值为根节点来构造二叉搜索树
如果之后再来复习,肯定会想:如果中间值有两个怎么办
那现在先举个例子说明一下:
[1,2,3,4,5,6]
这里如果取中间值会有两个数,分别是3和4
实际上这不影响我们去构造一颗高度平衡二叉搜索树,因为不论选3还是4作为根节点,其左或右子树多出的一个节点也不会破坏高度的平衡
在这里,我们默认取左边的值(后面会说明原因)
确定了根节点之后,还是像之前的构建二叉树的题目,通过递归不断分割左右区间,进而构建出根节点的左右子树
代码
分析
使用递归法
1、确定递归函数的参数和返回值
不要一写参数就下意识的填根节点,这里都还没有找出根节点呢
因为要通过分割数组来构建二叉树,所以输入参数中肯定有数组nums,以及用于分割的左右区间
并且,我们需要返回的是一颗二叉树,那么返回值显然就是该树的根节点了
TreeNode* traversal(vector<int> nums, int left, int right){
}
2、确定终止条件
同理,不要一写终止条件就下意识的root==NULL
这里的终止条件应该与左右边界有关
即当 left > right 时应该结束
TreeNode* traversal(vector<int> nums, int left, int right){
//确定终止条件
if(left > right) return NULL;
}
3、确定单层处理逻辑
现在要开始取数组的中间值并分割数组
TreeNode* traversal(vector<int> nums, int left, int right){
//确定终止条件
if(left > right) return NULL;
//确定单层处理逻辑
//取中间值
int mid = (right - left)/2 + left;
}
为什么这样取中间值?
因为如果直接(right + left) / 2,当right、left均为int下的最大值,会导致数据溢出
上述方法可以避免这种问题,详见
TreeNode* traversal(vector<int> nums, int left, int right){
//确定终止条件
if(left > right) return NULL;
//确定单层处理逻辑
//取中间值
int mid = (right - left)/2 + left;
//创建根节点
TreeNode* root = new TreeNode(nums[mid]);
//调用递归继续构建左右子树
root->left = traversal(nums, left, mid - 1);//跳过mid
root->right = traversal(nums, mid + 1, right);
return root;
}
注意,在分割数组时要跳过mid处的值
完整代码
class Solution {
public:
//确定递归函数的参数与返回值
TreeNode* traversal(vector<int>& nums, int left, int right){
//确定终止条件
if(left > right) return NULL;
//确定单层处理逻辑
//先找到数组里的中间值
int mid =(right - left) / 2 + left;//防止数据溢出
//初始化根节点
TreeNode* root = new TreeNode(nums[mid]);
//递归处理分割后数组的左区间和右区间
//注意要跳过mid
root->left = traversal(nums, left, mid - 1);
root->right = traversal(nums, mid + 1, right);
return root;
}
TreeNode* sortedArrayToBST(vector<int>& nums) {
return traversal(nums, 0 , nums.size() - 1);
}
};
构造二叉树的注意事项
1、找根节点
一般来说,没有特殊规定就找中间值作为根节点
本题中要求构建的二叉树为高度平衡的二叉搜索树,正好选中间值可以满足条件
2、根本原理
总结一下这几题构造二叉树的套路,无外乎:找根节点、递归分割数组构建左右子树
值得注意的是,在本题中,我们没有对nums本身进行操作,而是利用其下标进行的分割
而在之前做的几题里,我们分割数组时使用了**新建数组的方式
【LeetCode二叉树#19】有序数组转换为二叉搜索树(构造二叉树)的更多相关文章
- LeetCode:将有序数组转换为二叉搜索树【108】
LeetCode:将有序数组转换为二叉搜索树[108] 题目描述 将一个按照升序排列的有序数组,转换为一棵高度平衡二叉搜索树. 本题中,一个高度平衡二叉树是指一个二叉树每个节点 的左右两个子树的高度差 ...
- LeetCode 108. 将有序数组转换为二叉搜索树(Convert Sorted Array to Binary Search Tree) 14
108. 将有序数组转换为二叉搜索树 108. Convert Sorted Array to Binary Search Tree 题目描述 将一个按照升序排列的有序数组,转换为一棵高度平衡二叉搜索 ...
- Java实现 LeetCode 108 将有序数组转换为二叉搜索树
108. 将有序数组转换为二叉搜索树 将一个按照升序排列的有序数组,转换为一棵高度平衡二叉搜索树. 本题中,一个高度平衡二叉树是指一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1. 示例: ...
- [LeetCode] 108. 将有序数组转换为二叉搜索树
题目链接 : https://leetcode-cn.com/problems/convert-sorted-array-to-binary-search-tree/ 题目描述: 将一个按照升序排列的 ...
- 代码随想录算法训练营day23 | leetcode 669. 修剪二叉搜索树 ● 108.将有序数组转换为二叉搜索树 ● 538.把二叉搜索树转换为累加树
LeetCode 669. 修剪二叉搜索树 分析1.0 递归遍历树时删除符合条件(不在区间中)的节点-如何遍历如何删除 如果当前节点大于范围,递归左树,反之右树 当前节点不在范围内,删除它,把它的子树 ...
- [leetcode-108,109] 将有序数组转换为二叉搜索树
109. 有序链表转换二叉搜索树 Given a singly linked list where elements are sorted in ascending order, convert it ...
- LeetCode(108):将有序数组转换为二叉搜索树
Easy! 题目描述: 将一个按照升序排列的有序数组,转换为一棵高度平衡二叉搜索树. 本题中,一个高度平衡二叉树是指一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1. 示例: 给定有序数组 ...
- [LeetCode]105. 从前序与中序遍历序列构造二叉树(递归)、108. 将有序数组转换为二叉搜索树(递归、二分)
题目 05. 从前序与中序遍历序列构造二叉树 根据一棵树的前序遍历与中序遍历构造二叉树. 注意: 你可以假设树中没有重复的元素. 题解 使用HashMap记录当前子树根节点在中序遍历中的位置,方便每次 ...
- LeetCode刷题笔记-递归-将有序数组转换为二叉搜索树
题目描述 将一个按照升序排列的有序数组,转换为一棵高度平衡二叉搜索树. 本题中,一个高度平衡二叉树是指一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1. 示例: 给定有序数组: [-10, ...
- LeetCode【108. 将有序数组转换为二叉搜索树】
又是二叉树,最开始都忘记了二叉搜索树是什么意思,搜索了一下: 二叉搜索树:左节点都小于右节点,在这里就可以考虑将数组中的中间值作为根节点 平衡二叉树:就是左右节点高度不大于1 树就可以想到递归与迭代, ...
随机推荐
- [转帖]linux 下 {}大括号的用法
我们平时使用Linux的时候经常遇到这样一个问题,举例有这样一种情况:执行命令 $ cp /etc/apt/sources.list /etc/apt/sources.list.bak 这里面有个问题 ...
- [转帖]Linux kernel内存管理之overcommit相关参数
前言 了解 linux kernel内存管理,首先可以从用户空间的角度来看kernel的内存管理,执行ls /proc/sys/vm的命令,就可以看到vm运行的所有参数,其中就包含了跟overcomm ...
- [转载]Linux常用的可插拔认证模块(PAM)pam_limits.so、pam_rootok.so和pam_userdb.so的详解
Linux常用的可插拔认证模块(PAM)pam_limits.so.pam_rootok.so和pam_userdb.so的详解 https://blog.51cto.com/udb1680/1846 ...
- 某环境私有云 rpm 包安装失败总结
1. 最近公司同事说一个项目搭建环境时 rpm 安装mysql数据库会报错 错误图片主要如下: 第一个错误提示是 提示 /etc/host.conf line 2: bad command `nosp ...
- 【DS】P9062 [Ynoi2002] Adaptive Hsearch&Lsearch(区间最近点对)
Problem Link 给定平面上 \(n\) 个点,\(Q\) 次询问编号在 \([l,r]\) 内的点的最近点对.\(n,Q\le 2.5\times 10^5\). 技巧:平面网格化 乱搞都是 ...
- 你不知道的Linux shell操作
Linux Shell 脚本入门教程 Linux Shell 脚本是一种强大的工具,它允许您自动化日常任务和复杂操作.在本教程中,我们将逐步介绍几个实用的 Shell 脚本示例.每个示例都将详细说明, ...
- vue3中beforeRouteEnter 的使用和注意点
beforeRouteEnter 在vue3中的使用 有些时候,我们需要在知道是从哪一个页面过来的. 然后做一些逻辑处理 比如说:从A->B,B页面需要调用接口,回填B页面中的数据 B--> ...
- kettle(docker版)系列文章02---hello world
目标:将mysql库中表的数据定时转到另外一个表中 1.在mysql中新建目标表test_kettle,有字段id,productName,createtime 2.连接mysql数据库 DB连接-- ...
- IM开源项目OpenIM部署文档-从准备工作到nginx配置
IM开源项目OpenIM部署文档-从准备工作到nginx配置 2022-11-14 22:27·OpenIM 一.准备工作 运行环境 linux系统即可, Ubuntu 7.5.0-3ubuntu1~ ...
- 图解Java原理
1:强制类型转换数据溢出 2:顺序结构的流程图 3:单if语句的流程图 4:标准if-else语句的流程图 5:扩展if-else语句的流程图 6:for循环流程图