LeetCode654. 最大二叉树
题目链接:https://leetcode.cn/problems/maximum-binary-tree/description/
题目叙述
给定一个不重复的整数数组 nums 。 最大二叉树 可以用下面的算法从 nums 递归地构建:
创建一个根节点,其值为 nums 中的最大值。
递归地在最大值 左边 的 子数组前缀上 构建左子树。
递归地在最大值 右边 的 子数组后缀上 构建右子树。
返回 nums 构建的 最大二叉树 。
示例 1:

输入:nums = [3,2,1,6,0,5]
输出:[6,3,5,null,2,0,null,null,1]
解释:递归调用如下所示:
- [3,2,1,6,0,5] 中的最大值是 6 ,左边部分是 [3,2,1] ,右边部分是 [0,5] 。
- [3,2,1] 中的最大值是 3 ,左边部分是 [] ,右边部分是 [2,1] 。
- 空数组,无子节点。
- [2,1] 中的最大值是 2 ,左边部分是 [] ,右边部分是 [1] 。
- 空数组,无子节点。
- 只有一个元素,所以子节点是一个值为 1 的节点。
- [0,5] 中的最大值是 5 ,左边部分是 [0] ,右边部分是 [] 。
- 只有一个元素,所以子节点是一个值为 0 的节点。
- 空数组,无子节点。
- [3,2,1] 中的最大值是 3 ,左边部分是 [] ,右边部分是 [2,1] 。
示例 2:

输入:nums = [3,2,1]
输出:[3,null,2,null,1]
提示:
1 <= nums.length <= 1000
0 <= nums[i] <= 1000
nums 中的所有整数 互不相同
思路:
构造树一般采用的是前序遍历,因为先构造中间节点,然后递归构造左子树和右子树。
我们来走一下递归的三步法:
递归函数的参数和返回值:返回值明显为TreeNode的节点类型,参数我们需要传入一个数组
递归结束的条件:题目中说了输入的数组大小一定是大于等于1的,所以我们不用考虑小于1的情况,那么当递归遍历的时候,如果传入的数组大小为1,说明遍历到了叶子节点了。
那么应该定义一个新的节点,并把这个数组的数值赋给新的节点,然后返回这个节点。 这表示一个数组大小是1的时候,构造了一个新的节点,并返回。
TreeNode* node = new TreeNode(0);
if (nums.size() == 1) {
node->val = nums[0];
return node;
}
3.递归的单层逻辑:
我们需要找出这个数组中的最大值,然后对这个数组进行分割,最大值左边的数组来构造左子树,最大值右边的数组来构造右子树,不过在此之前,我们还得找到最大值和最大值所对应的下标
//找到了这个数组中的最大的元素和最大元素所在的下标
int maxValue = 0;
int index = 0;
for (int i = 0; i < nums.size(); i++) {
if (nums[i] > maxValue) {
index = i;
maxValue = nums[i];
}
}
//对根节点进行赋值
node->val = maxValue;
然后就是对根节点node的左子树和右子树进行构造的过程,我们可以使用两个数组,来存储最大值左边的序列和最大值右边的序列
if (index >= 1) {
//因为vector的拷贝构造函数是左开右闭的逻辑
vector<int> newVec(nums.begin(), nums.begin() + index);
node->left = constructMaximumBinaryTree(newVec);
}
//确保右边子树的元素个数≥1
if ((nums.size() - 1) - index > 0) {
vector<int> newVec(nums.begin() + index + 1, nums.end());
node->right = constructMaximumBinaryTree(newVec);
}
return node;
这几步做完以后,基本就完成了
//最大二叉树
class Solution {
public:
TreeNode* constructMaximumBinaryTree(vector<int>& nums) {
TreeNode* node = new TreeNode(0);
if (nums.size() == 1) {
node->val = nums[0];
return node;
}
//找到了这个数组中的最大的元素和最大元素所在的下标
int maxValue = 0;
int index = 0;
for (int i = 0; i < nums.size(); i++) {
if (nums[i] > maxValue) {
index = i;
maxValue = nums[i];
}
}
//对根节点进行赋值
node->val = maxValue;
//对左子树进行构造(确保左边数组的元素个数≥1)
if (index >= 1) {
vector<int> newVec(nums.begin(), nums.begin() + index);
node->left = constructMaximumBinaryTree(newVec);
}
//确保右边子树的元素个数≥1
if ((nums.size() - 1) - index > 0) {
vector<int> newVec(nums.begin() + index + 1, nums.end());
node->right = constructMaximumBinaryTree(newVec);
}
return node;
}
};
进阶
我们可以不适用额外的数组空间,我们可以直接对传入的数组的下标进行操作
class Solution {
public:
TreeNode* traversal(vector<int> &nums,int left,int right){
//当左区间≥右区间,就返回
if(left>=right) return nullptr;
//记录最大值的下标
int maxValueIndex=left;
for(int i=left+1;i<right;i++){
if(nums[i]>nums[maxValueIndex]) maxValueIndex=i;
}
//构造根节点
TreeNode* node=new TreeNode(nums[maxValueIndex]);
//构造左子树和右子树
node->left=traversal(nums,left,maxValueIndex);
node->right=traversal(nums,maxValueIndex+1,right);
//返回根节点
return node;
}
TreeNode* constructMaximumBinaryTree(vector<int>& nums) {
return traversal(nums,0,nums.size());
}
};
总结
注意类似用数组构造二叉树的题目,每次分隔尽量不要定义新的数组,而是通过下标索引直接在原数组上操作,这样可以节约时间和空间上的开销。
什么时候递归函数前面加if,什么时候不加if?
其实就是不同代码风格的实现,一般情况来说:如果让空节点(空指针)进入递归,就不加if,如果不让空节点进入递归,就加if限制一下, 终止条件也会相应的调整。
LeetCode654. 最大二叉树的更多相关文章
- [Swift]LeetCode654. 最大二叉树 | Maximum Binary Tree
Given an integer array with no duplicates. A maximum tree building on this array is defined as follo ...
- LeetCode通关:连刷三十九道二叉树,刷疯了!
分门别类刷算法,坚持,进步! 刷题路线参考:https://github.com/youngyangyang04/leetcode-master 大家好,我是拿输出博客来督促自己刷题的老三,这一节我们 ...
- [数据结构]——二叉树(Binary Tree)、二叉搜索树(Binary Search Tree)及其衍生算法
二叉树(Binary Tree)是最简单的树形数据结构,然而却十分精妙.其衍生出各种算法,以致于占据了数据结构的半壁江山.STL中大名顶顶的关联容器--集合(set).映射(map)便是使用二叉树实现 ...
- 二叉树的递归实现(java)
这里演示的二叉树为3层. 递归实现,先构造出一个root节点,先判断左子节点是否为空,为空则构造左子节点,否则进入下一步判断右子节点是否为空,为空则构造右子节点. 利用层数控制迭代次数. 依次递归第二 ...
- c 二叉树的使用
简单的通过一个寻找嫌疑人的小程序 来演示二叉树的使用 #include <stdio.h> #include <stdlib.h> #include <string.h& ...
- Java 二叉树遍历右视图-LeetCode199
题目如下: 题目给出的例子不太好,容易让人误解成不断顺着右节点访问就好了,但是题目意思并不是这样. 换成通俗的意思:按层遍历二叉树,输出每层的最右端结点. 这就明白时一道二叉树层序遍历的问题,用一个队 ...
- 数据结构:二叉树 基于list实现(python版)
基于python的list实现二叉树 #!/usr/bin/env python # -*- coding:utf-8 -*- class BinTreeValueError(ValueError): ...
- [LeetCode] Path Sum III 二叉树的路径和之三
You are given a binary tree in which each node contains an integer value. Find the number of paths t ...
- [LeetCode] Find Leaves of Binary Tree 找二叉树的叶节点
Given a binary tree, find all leaves and then remove those leaves. Then repeat the previous steps un ...
- [LeetCode] Verify Preorder Serialization of a Binary Tree 验证二叉树的先序序列化
One way to serialize a binary tree is to use pre-oder traversal. When we encounter a non-null node, ...
随机推荐
- Python多线程、多进程编程
1 简介 参考:https://www.bilibili.com/video/BV1bK411A7tV?spm_id_from=333.999.0.0 python线程池ThreadPoolExecu ...
- proteus 器件名称被软件篡改bug的解决方案
proteus v7.8 器件名称被软件篡改bug 的解决方案 BUG描述 在做单片机实验时,发现从某一个时间保存的设计图文件开始,在添加新的电子元件时会出现部分旧元件的名称被捆绑替换为新元件的名称, ...
- jq data方法
data() 是 jQuery 的方法之一,用于在元素上存储和获取数据.它允许你将任意类型的数据附加到一个或多个元素上,并且可以通过选择器或元素对象来访问和操作这些数据. 代码中,_t.selectB ...
- THUWC 2024 游记
其实这个游记也没啥好写的-- day 0 上午做动车两个小时到重庆,路上玩了 1.5h 的星露谷. 下午去巴蜀中学报道试机,系统是 Ubuntu Jammy,大大的好评,只是桌面是 Xubuntu/X ...
- 使用线程池实现为多个客户端提供Echo服务
import java.io.*; import java.net.ServerSocket; import java.net.Socket; import java.util.Scanner; im ...
- 在线IP归属地查询工具
在线IP地址归属地查询工具,通过该工具可以查询指定IP的物理地址或域名服务器的IP和物理地址,及所在国家或城市IP归属地,数据为纯真IP. 在线IP归属地查询工具
- LocalDateTime与LocalDate之间转换
LocalDateTime与LocalDate之间转换 //LocalDateTime转换LocalDate LocalDateTime now2 = LocalDateTime.now(); Loc ...
- svn服务端安装和使用
首先去官网下载安装包 点我下载 下载完了以后选择安装路径然后一直next就可以了 安装完了以后在开始菜单里面找到svn 打开 如何使用? 这里是创建代码管理的存储库 点击 repositories ...
- python selenium UI自动化操作iframe及返回默认页面
页面操作的场景:进到到页面A,选择页面A里面的记录,点击签约, 弹出一个弹窗B,弹窗B的内容是协议及同意按钮或其他非同意的提示信息,主要的操作,打开页面A,点击签约,点击同意,操作完成 分析页面的组成 ...
- CentOS8 安装ansible
# 安装epel扩展源 yum install https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm -y # ...