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, ...
随机推荐
- MySQL学习笔记-数据定义语言
SQL-数据定义语言(DDL) 一.操作数据库 1.查询 # 查询所有数据库 show databases; # 查询当前数据库 select database(); 2.创建 create data ...
- Atlas快速入门
先说一些废话 之前的公司在数据中台的项目上调研决定启用了Atlas作为我们数据血缘管理的工具,让我给大家写了一份Atlas快速入门的文档,所以在这里我将这篇文档以一个纯新手视角的方式再一次优化,希望能 ...
- [SWPUCTF 2021 新生赛]easyrce
这道题比较简单,打开环境一看就只需要构造一个get传参的命令就行,我们就看一下有些什么文件,构造payload: ?url=system ("ls /"); 看到有个 flllll ...
- (二)requests-爬取国家药监局生产许可证数据
首先访问这个页面 url = 'http://125.35.6.84:81/xk/' 我们的目标是抓取这里的每一个企业的详情页数据,但是可以发现这里只有企业的简介信息,所以这就意味着我们要发送两次ge ...
- 590. N 叉树的后序遍历 | Javascript 递归实现
题目 题目链接:590. N 叉树的后序遍历 解题思路 递归后续遍历,正常的思路 然后有一个要注意的地方就是如果js定义了全局变量来存储结果,每次调用函数之前一定要记得清空,否则答案会带上之前的结果. ...
- DotNet Web应用单文件部署系列
目录 一. pubxml文件配置 二. 打包wwwroot文件夹 三. 混淆dll文件 四. csproj文件配置 五. 批处理 六. Windows服务安装 七. ...
- PPP协议简介
转载出处:https://blog.csdn.net/csucxcc/article/details/1684416 PPP(Point-to-Point Protocol)协议是在SLIP的基础上发 ...
- 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 ...
- 3D捕鱼大富翁源码分析
今天接受了一个捕鱼的源码,技术栈采用: 客户端:Unity 服务端:Java 数据库:mysql 缓存:redis 先来几张成品图 编辑编辑 编辑编辑 编辑 在代码中看到有腾讯推广渠道, ...
- Kubernetes(五) Pod控制器详解
Pod控制器详解 本章主要介绍Pod控制器的详细使用 1. Pod控制器介绍 在kubernetes中,按照pod的创建方式可以将其分为2类: 自主式pod:kubernetes直接创建出来的pod, ...