题目链接: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 的节点。
      • 空数组,无子节点。

示例 2:

输入:nums = [3,2,1]

输出:[3,null,2,null,1]

提示:

1 <= nums.length <= 1000

0 <= nums[i] <= 1000

nums 中的所有整数 互不相同

思路:

构造树一般采用的是前序遍历,因为先构造中间节点,然后递归构造左子树和右子树。

我们来走一下递归的三步法:

  1. 递归函数的参数和返回值:返回值明显为TreeNode的节点类型,参数我们需要传入一个数组

  2. 递归结束的条件:题目中说了输入的数组大小一定是大于等于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. 最大二叉树的更多相关文章

  1. [Swift]LeetCode654. 最大二叉树 | Maximum Binary Tree

    Given an integer array with no duplicates. A maximum tree building on this array is defined as follo ...

  2. LeetCode通关:连刷三十九道二叉树,刷疯了!

    分门别类刷算法,坚持,进步! 刷题路线参考:https://github.com/youngyangyang04/leetcode-master 大家好,我是拿输出博客来督促自己刷题的老三,这一节我们 ...

  3. [数据结构]——二叉树(Binary Tree)、二叉搜索树(Binary Search Tree)及其衍生算法

    二叉树(Binary Tree)是最简单的树形数据结构,然而却十分精妙.其衍生出各种算法,以致于占据了数据结构的半壁江山.STL中大名顶顶的关联容器--集合(set).映射(map)便是使用二叉树实现 ...

  4. 二叉树的递归实现(java)

    这里演示的二叉树为3层. 递归实现,先构造出一个root节点,先判断左子节点是否为空,为空则构造左子节点,否则进入下一步判断右子节点是否为空,为空则构造右子节点. 利用层数控制迭代次数. 依次递归第二 ...

  5. c 二叉树的使用

    简单的通过一个寻找嫌疑人的小程序 来演示二叉树的使用 #include <stdio.h> #include <stdlib.h> #include <string.h& ...

  6. Java 二叉树遍历右视图-LeetCode199

    题目如下: 题目给出的例子不太好,容易让人误解成不断顺着右节点访问就好了,但是题目意思并不是这样. 换成通俗的意思:按层遍历二叉树,输出每层的最右端结点. 这就明白时一道二叉树层序遍历的问题,用一个队 ...

  7. 数据结构:二叉树 基于list实现(python版)

    基于python的list实现二叉树 #!/usr/bin/env python # -*- coding:utf-8 -*- class BinTreeValueError(ValueError): ...

  8. [LeetCode] Path Sum III 二叉树的路径和之三

    You are given a binary tree in which each node contains an integer value. Find the number of paths t ...

  9. [LeetCode] Find Leaves of Binary Tree 找二叉树的叶节点

    Given a binary tree, find all leaves and then remove those leaves. Then repeat the previous steps un ...

  10. [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, ...

随机推荐

  1. MySQL学习笔记-数据定义语言

    SQL-数据定义语言(DDL) 一.操作数据库 1.查询 # 查询所有数据库 show databases; # 查询当前数据库 select database(); 2.创建 create data ...

  2. Atlas快速入门

    先说一些废话 之前的公司在数据中台的项目上调研决定启用了Atlas作为我们数据血缘管理的工具,让我给大家写了一份Atlas快速入门的文档,所以在这里我将这篇文档以一个纯新手视角的方式再一次优化,希望能 ...

  3. [SWPUCTF 2021 新生赛]easyrce

    这道题比较简单,打开环境一看就只需要构造一个get传参的命令就行,我们就看一下有些什么文件,构造payload: ?url=system ("ls /"); 看到有个 flllll ...

  4. (二)requests-爬取国家药监局生产许可证数据

    首先访问这个页面 url = 'http://125.35.6.84:81/xk/' 我们的目标是抓取这里的每一个企业的详情页数据,但是可以发现这里只有企业的简介信息,所以这就意味着我们要发送两次ge ...

  5. 590. N 叉树的后序遍历 | Javascript 递归实现

    题目 题目链接:590. N 叉树的后序遍历 解题思路 递归后续遍历,正常的思路 然后有一个要注意的地方就是如果js定义了全局变量来存储结果,每次调用函数之前一定要记得清空,否则答案会带上之前的结果. ...

  6. DotNet Web应用单文件部署系列

    目录 一.    pubxml文件配置 二.    打包wwwroot文件夹 三.    混淆dll文件 四.    csproj文件配置 五.    批处理 六.    Windows服务安装 七. ...

  7. PPP协议简介

    转载出处:https://blog.csdn.net/csucxcc/article/details/1684416 PPP(Point-to-Point Protocol)协议是在SLIP的基础上发 ...

  8. detect.py - yolov5master nvidia jetson agx xavier for mask with UART

    import argparse import time from pathlib import Path import cv2 import torch import torch.backends.c ...

  9. 3D捕鱼大富翁源码分析

    ​ 今天接受了一个捕鱼的源码,技术栈采用: 客户端:Unity 服务端:Java 数据库:mysql 缓存:redis 先来几张成品图 ​编辑​编辑 ​编辑​编辑 ​编辑 在代码中看到有腾讯推广渠道, ...

  10. Kubernetes(五) Pod控制器详解

    Pod控制器详解 本章主要介绍Pod控制器的详细使用 1. Pod控制器介绍 在kubernetes中,按照pod的创建方式可以将其分为2类: 自主式pod:kubernetes直接创建出来的pod, ...