【1130. 叶值的最小代价生成树】

news2024/12/28 17:53:03

来源:力扣(LeetCode)

描述:

给你一个正整数数组 arr,考虑所有满足以下条件的二叉树:

  • 每个节点都有 0 个或是 2 个子节点。
  • 数组 arr 中的值与树的中序遍历中每个叶节点的值一一对应。
  • 每个非叶节点的值等于其左子树和右子树中叶节点的最大值的乘积。

在所有这样的二叉树中,返回每个非叶节点的值的最小可能总和。这个和的值是一个 32 位整数。

如果一个节点有 0 个子节点,那么该节点为叶节点。

示例 1:

1

输入:arr = [6,2,4]
输出:32
解释:有两种可能的树,第一种的非叶节点的总和为 36 ,第二种非叶节点的总和为 32

示例 2:

2

输入:arr = [4,11]
输出:44

提示:

  • 2 <= arr.length <= 40
  • 1 <= arr[i] <= 15
  • 答案保证是一个 32 位带符号整数,即小于 231

方法一:动态规划

已知数组 arr 与二叉树的中序遍历的所有叶子节点对应,并且二叉树的每个节点都有 0 个节点或 2 个节点。考虑数组 arr 可以生成的所有二叉树,我们可以将 arr 切分成任意两个非空子数组,分别对应左子树和右子树,然后递归地对两个非空子树组执行相同的操作,直到子数组大小等于 1,即叶子节点,那么一种切分方案对应一个合法的二叉树。

使用 dp[i][j] 表示子数组 [i, j] (i ≤ j) 对应的子树所有非叶子节点的最小总和,那么 dp[i][j] 可以通过切分子树求得,状态转移方程如下:

方法一

其中 mik 表示子数组 [i,k] 的最大值,可以预先计算并保存下来。

代码:

class Solution {
public:
    int mctFromLeafValues(vector<int>& arr) {
        int n = arr.size();
        vector<vector<int>> dp(n, vector<int>(n, INT_MAX / 4)), mval(n, vector<int>(n));
        for (int j = 0; j < n; j++) {
            mval[j][j] = arr[j];
            dp[j][j] = 0;
            for (int i = j - 1; i >= 0; i--) {
                mval[i][j] = max(arr[i], mval[i + 1][j]);
                for (int k = i; k < j; k++) {
                    dp[i][j] = min(dp[i][j], dp[i][k] + dp[k + 1][j] + mval[i][k] * mval[k + 1][j]);
                }
            }
        }
        return dp[0][n - 1];
    }
};

执行用时:4 ms, 在所有 C++ 提交中击败了77.21%的用户
内存消耗:9 MB, 在所有 C++ 提交中击败了25.58%的用户
复杂度分析
时间复杂度:O(n3),其中 n 是数组 arr 的长度。三重循环需要 O(n3) 的空间。
空间复杂度:O(n2)。保存 dp 和 mval 需要 O(n2) 的空间。

方法二:单调栈

方法一的思路是自上而下构建二叉树,这里我们可以尝试自下而上构建二叉树:

  1. 选择 arr 两个相邻的值,即两个节点,将它们作为一个新节点的左子节点和右子节点;
  2. 将这个新节点在数组 arr 替代这两个节点;
  3. 如果 arr 剩余的元素数目大于 1,执行步骤 1,否则终止,那么剩余的节点就是构建的二叉树的根节点。

问题可以转化为:给定一个数组 arr,不断地合并相邻的数,合并代价为两个数的乘积,合并之后的数为两个数的最大值,直到数组只剩一个数,求最小合并代价和。

假设一个数 arr[i] (0 < i < n − 1),满足 arr[i−1] ≥ arr[i] 且 arr[i] ≤ arr[i+1],如果 arr[i−1] ≤ arr[i+1],那么优先将 arr[i] 与 arr[i−1] 合并是最优的,反之如果 arr[i−1] > arr[i+1],那么优先将 arr[i] 与 arr[i+1] 合并是最优的。

按照这种思路,套用单调栈算法(栈元素从底到顶是严格递减的),我们遍历数组 arr,记当前遍历的值为 x。

如果栈非空且栈顶元素小于等于 x,那么说明栈顶元素(类似于 arr[i])是符合前面所说的最优合并的条件,将栈顶元素 y 出栈:

  • 如果栈空或栈顶元素大于 x,那么将 y 与 x 合并,合并代价为 x × y,合并之后的值为 x;
  • 否则将 y 与栈顶元素合并,合并代价为 y 与栈顶元素的乘积,合并之后的值为栈顶元素。

重复以上过程直到栈空或栈顶元素大于 x,然后将 x 入栈。

经过以上合并过程后,栈中的元素从底到顶是严格递减的,因此可以不断地将栈顶的两个元素出栈,合并,再入栈,直到栈元素数目小于 2。返回最终合并代价和即可。

代码:

class Solution {
public:
    int mctFromLeafValues(vector<int>& arr) {
        int res = 0;
        stack<int> stk;
        for (int x : arr) {
            while (!stk.empty() && stk.top() <= x) {
                int y = stk.top();
                stk.pop();
                if (stk.empty() || stk.top() > x) {
                    res += y * x;
                } else {
                    res += stk.top() * y;
                }
            }
            stk.push(x);
        }
        while (stk.size() >= 2) {
            int x = stk.top();
            stk.pop();
            res += stk.top() * x;
        }
        return res;
    }
};

执行用时:0 ms, 在所有 C++ 提交中击败了100.00%的用户
内存消耗:8.1 MB, 在所有 C++ 提交中击败了76.28%的用户
复杂度分析
时间复杂度:O(n),其中 n 为数组 arr 的长度。每次循环都有入栈或出栈操作,总次数不超过 2 × n,因此时间复杂度为 O(n)。
空间复杂度:O(n)。栈 stk 需要 O(n) 的空间。
author:LeetCode-Solution

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/592353.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

用arcgis for javascript 开发一个简单的二维地图(入门案例)

效果如图&#xff1a; 一、引入arcgis <link rel"stylesheet" href"https://js.arcgis.com/4.26/esri/themes/light/main.css" /> <script src"https://js.arcgis.com/4.26/"></script>2.加载模块 使用第二个标记从 API 加…

第四期:栈与队列的交换游戏

目录 1. 用队列实现栈2. 用栈实现队列3. 答案3.1 用队列实现栈3.2 用栈实现队列 PS&#xff1a;每道题解题方法不唯一&#xff0c;欢迎讨论&#xff01;每道题后都有解析帮助你分析做题&#xff0c;答案在最下面&#xff0c;关注博主每天持续更新。 1. 用队列实现栈 题目描述 …

RISC-V IDE MRS使用笔记(八):实现局域网下的远程调试功能

RISC-V IDE MRS使用笔记(八)&#xff1a;实现局域网下的远程调试功能 1.原理介绍 MRS调试时上位机与硬件的通信基于gdb客户端与服务端的连接。调试时&#xff0c;首先启动openocd以挂载gdbserver的服务到指定端口上。通信建立后&#xff0c;监听到界面操作后以gdb指令的形式发…

Mapbox字体切片工具fontnik部署与使用

我们在使用Mapbox的时候,不同的图层可以配置不同的字体。Mapbox主要通过分片加载SDF格式字体的方式,将比较大的字体文件传输到前端渲染使用。fontnik可以将字体文件也制作成pbf切片文件,在访问的时候,图中大括号的位置,style中的glyphs,需要根据实际字体和切片索引进行替…

基于html+css的图展示101

准备项目 项目开发工具 Visual Studio Code 1.44.2 版本: 1.44.2 提交: ff915844119ce9485abfe8aa9076ec76b5300ddd 日期: 2020-04-16T16:36:23.138Z Electron: 7.1.11 Chrome: 78.0.3904.130 Node.js: 12.8.1 V8: 7.8.279.23-electron.0 OS: Windows_NT x64 10.0.19044 项目…

硬件速攻-SG90舵机(180和360)

外观 180度和360度的区别 180度的舵机可以控制角度 360度的舵机只能控制正反转和速度 驱动逻辑 180度 t 0.5ms——————转动 0 t 1.0ms——————转动 45 t 1.5ms——————转动 90 t 2.0ms——————转动 135 t 2.5ms——————转动180 360度 t 0.5ms—…

微信小程序授权给第三方平台后,“消息与事件接收URL“接收不到客服消息

记录微信小程序授权第三方平台遇到的问题 问题表现为&#xff1a;微信小程序授权给第三方平台后&#xff0c;在小程序客服发送消息&#xff0c;消息与事件接收URL接收不到客服消息 小程序授权配置如下&#xff1a; 1、小程序已授权第三方平台“小程序客服管理”权限 2、小程…

韧性数据安全体系缘起与三个目标 |CEO专栏

今年4月&#xff0c;美创科技在数据安全领域的新探索——“韧性”数据安全防护体系框架正式发布亮相。 为帮您更深入了解“韧性数据安全”&#xff0c;我们特别推出专栏“构建适应性进化的韧性数据安全体系”&#xff0c;CEO柳遵梁亲自执笔&#xff0c;进行系列解读分享。 首期…

4.4. 对象序列化与反序列化

在本节中&#xff0c;我们将详细讨论Java中的对象序列化与反序列化概念、使用方法以及实例。对象序列化是将对象的状态信息转换为字节流的过程&#xff0c;而反序列化则相反&#xff0c;是将字节流恢复为对象的过程。 4.4.1 为什么需要对象序列化&#xff1f; 对象序列化的主…

SDN笔记

SDN是软件定义网络的简称&#xff0c;在SDN中&#xff0c;网络的控制面与数据面分离&#xff0c;并且通过中心控制器进行统一管理。SDN的主要目标是提高网络的灵活性、可编程性和智能化程度&#xff0c;从而更好地适应不断变化的业务需求。SDN可以通过控制器来管理网络设备&…

Day57【动态规划】647.回文子串、516.最长回文子序列

647.回文子串 力扣题目链接/文章讲解 视频讲解 1、确定 dp 数组下标及值含义 dp[i][j]&#xff1a;表示区间范围为 [i, j] 的子串是否为回文串&#xff08;j > i&#xff09; 这样定义才方便我们的递推&#xff01;怎么想到的&#xff1f;回文串需要对比串的两端&#…

【大数据学习篇11】Spark项目实战~网站转化率统计

学习目标/Target 掌握广告点击流实时统计实现思路 掌握利用Kafka生产用户广告点击流数据 了解数据库设计 掌握如何创建Spark Streaming连接 掌握利用Spark Streaming读取业务数据 掌握利用Spark读取黑名单用户 掌握利用Spark Streaming过滤黑名单用户 掌握利用Spark St…

利用ArcGIS与CAD制作设计底图

准备工作&#xff1a; 1、需要用到的软件&#xff1a;ArcGIS软件、AutoCAD&#xff1b; 2、卫星图数据、矢量数据&#xff08;因数据涉密&#xff0c;需要的同事请联系科技小组拷贝&#xff0c;并签署保密协议&#xff0c;严格履行保密责任&#xff09;。 现在&#xff0c;保…

小程序开发逆势爆发,如此会无疾而终?

2019年&#xff0c;小程序迎来了爆发式的增长&#xff0c;一年时间&#xff0c;微信小程序的活跃用户达到了3.2亿&#xff0c;日活跃用户高达5.4亿&#xff0c;在这巨大的数据背后&#xff0c;是无数商家和企业的努力与付出。小程序开发的优势显而易见&#xff0c;不少商家和企…

for in和for of的区别

for in for in 使用于可枚举的数据 如 对象 数组 字符串 什么是可枚举的&#xff1a;属性的enumerable值为true&#xff0c;表示可枚举 可以通过es7新增的属性 Object.getOwnPropertyDescriptors()验证 查看 Object.getOwnPropertyDescriptor() 方法用于 返回 指定 对象 上一个…

kubernetes安装dashboard教程

kubernetes安装dashboard教程 前提&#xff1a; kubernetes集群安装完毕 安装&#xff1a; 1.到github获取配置文件 github下面给出方法说使用下面的直接执行就可以了&#xff0c;但是最近不知道为何找不到地址。 kubectl apply -f https://raw.githubusercontent.com/ku…

查看网页cookie的方法

方法一 进入目标网页后&#xff0c; 按F12&#xff0c;找到Console&#xff0c;在filter框内输入&#xff1a;document.cookie&#xff0c;然后回车 如果filter框内输入后下面没有显示&#xff0c;需要在2的位置输入document.cookie回车 其中红色的内容即为cookie内容 不过这…

如何使用OpenAI GPT-3进行自然语言生成?

自然语言生成是一项非常引人注目的技术&#xff0c;可以让计算机像人类一样理解、生成自然语言文本。最近&#xff0c;OpenAI发布了一种名为GPT-3的巨型语言模型&#xff0c;它是史上最强大的自然语言生成模型之一。在本文中&#xff0c;我将介绍如何使用GPT-3进行自然语言生成…

vue-admin-template后台管理模板在windows/linux/maxos使用

能用克隆与编译运行命令: # 克隆项目 git clone https://github.com/PanJiaChen/vue-admin-template.git# 进入项目目录 cd vue-admin-template# 安装依赖 npm install# 开发者模式运行 npm run dev 1. macos: 降级为NODEJS 16运行工程: export NODE_OPTIONS--openssl-legac…

【服务器】本地搭建PHP简单Imagewheel私人云图床

文章目录 1.前言2. Imagewheel网站搭建2.1. Imagewheel下载和安装2.2. Imagewheel网页测试2.3.cpolar的安装和注册 3.本地网页发布3.1.Cpolar临时数据隧道3.2.Cpolar稳定隧道&#xff08;云端设置&#xff09;3.3.Cpolar稳定隧道&#xff08;本地设置&#xff09; 4.公网访问测…