首页 星云 工具 资源 星选 资讯 热门工具
:

PDF转图片 完全免费 小红书视频下载 无水印 抖音视频下载 无水印 数字星空

LeetCode654. 最大二叉树

编程知识
2024年07月28日 20:26

题目链接: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限制一下, 终止条件也会相应的调整。

From:https://www.cnblogs.com/Tomorrowland/p/18328894
本文地址: http://shuzixingkong.net/article/532
0评论
提交 加载更多评论
其他文章 C语言中的断言函数assert
简介 assert 是 C 语言中的一个宏,用于在程序运行时进行条件检查,主要用于调试目的。它在 &lt;assert.h&gt; 头文件中定义,用于验证程序中的假设条件是否成立,如果不成立,程序将打印错误信息并终止执行。 特点 调试用途:主要用于捕获程序中的逻辑错误或不期望的条件。 可移除:通过定
萌新的装机体验(持续更新)
萌新的装机体验 起因 作为一名 OIer,平日划水的方式无非就是看看 edge 首页和知乎(当然如果教练不在就上 B 站了)。有一天在 edge 主页上忽然看到了一个 5000 元主机的装机体验,看完之后就想换台电脑了。 家里的那台电脑是我小学毕业的时候和我爸自己装的。当时什么都不懂(但以为自己很懂
408数据结构树算法
第四章 树 4.1 二叉树的顺序存储 #define MAXSIZE 16 typedef int ElemType; typedef struct { ElemType data[MAXSIZE]; int size; }Tree; //初始化二叉树 void initTree(Tree&amp;
408数据结构树算法 408数据结构树算法
Python 代码中的 yield 到底是什么?
在Python编程中,有一个强大而神秘的关键字,那就是yield。初学者常常被它搞得晕头转向,而高级开发者则借助它实现高效的代码。到底yield是什么?它又是如何在Python代码中发挥作用的呢?让我们一起来揭开它的面纱。 Python里的一个非常重要但也颇具迷惑性的关键词——yield。 什么是y
Python 代码中的 yield 到底是什么? Python 代码中的 yield 到底是什么? Python 代码中的 yield 到底是什么?
(2024最新)有效解决OpenAI Chatgpt Plus升级报错【您的银行卡被拒绝了/your card has been declined」,不用再问怎么办?
OpenAI升级ChatGPT plus时可能会遇到升级报错【您的银行卡被拒绝了/your card has been declined」,教你快速解决并升级成功
(2024最新)有效解决OpenAI Chatgpt Plus升级报错【您的银行卡被拒绝了/your card has been declined」,不用再问怎么办? (2024最新)有效解决OpenAI Chatgpt Plus升级报错【您的银行卡被拒绝了/your card has been declined」,不用再问怎么办?
SpringBoot2.7还是任性的,就是不支持Logback1.3,你能奈他何
开心一刻 今天上午,同事群中的刘总私聊我 刘总:你来公司多久了 我:一年了,刘总 刘总:你还年轻,机会还很多,年底了,公司要裁员 刘总语重心长的继续说到:以后我们常联系,无论以后你遇到什么困难,找我,我会尽量帮你! 我:所以了,我是被裁了吗,呵,我爸知道吗? 刘总:知道,今天上午保安部已经出名单了,
SpringBoot2.7还是任性的,就是不支持Logback1.3,你能奈他何 SpringBoot2.7还是任性的,就是不支持Logback1.3,你能奈他何 SpringBoot2.7还是任性的,就是不支持Logback1.3,你能奈他何
《最新出炉》系列入门篇-Python+Playwright自动化测试-56- 多文件上传 - 下篇
1.简介 前边的两篇文章中,宏哥分别对input控件上传文件和非input控件上传文件进行了从理论到实践地讲解和介绍,但是后来又有人提出疑问,前边讲解和介绍的都是上传一个文件,如果上传多个文件,Playwright是如何实现的呢?宏哥看了一下官方的API也有上传多个文件的API,那么今天就来讲解和介
《最新出炉》系列入门篇-Python+Playwright自动化测试-56- 多文件上传 - 下篇 《最新出炉》系列入门篇-Python+Playwright自动化测试-56- 多文件上传 - 下篇 《最新出炉》系列入门篇-Python+Playwright自动化测试-56- 多文件上传 - 下篇
这才是 PHP 高性能框架 Workerman 的立命之本
在这个大家都崇尚高性能的时代,程序员的谈笑间句句都离不开高性能,仿佛嘴角边不挂着「高性能」三个字都会显得自己很 Low,其中众所皆知的 Nginx 就是高性能的代表。
这才是 PHP 高性能框架 Workerman 的立命之本