LC-1130. 叶值的最小代价生成树(贪心、区间DP、单调栈)

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

难度中等272

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

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

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

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

示例 1:

img

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

示例 2:

img

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

提示:

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

贪心

class Solution {public int mctFromLeafValues(int[] arr) {// 哈夫曼树 : 每次选择两个值最小的进行合并List<Integer> list = new ArrayList<>();for(int i = 0; i < arr.length; i++){list.add(arr[i]);}int ans = 0;while(list.size() > 1){int i = 1;int mul = Integer.MAX_VALUE, tmp = 1;while(i < list.size()){if(mul > list.get(i) * list.get(i-1)){mul = list.get(i) * list.get(i-1);tmp = i;}i += 1;}// 答案加上当前最小乘积,并删除两个数中较小的节点ans += mul;if(list.get(tmp) > list.get(tmp-1)) list.remove(tmp-1);else list.remove(tmp);}return ans;}
}

记忆化搜索 ==> 动态规划

打开思路的几个关键点:

1、对于每个区间[L, R]的叶子结点,最终会汇聚成一个根节点,但这个根节点会根据[L, R]中的子区间划分方式的不同而不同,我们要做的就是要求其中的最小的

2、不要纠结“树的形状”、“树有几层”等等的关于“树”相关的东西,区间划分一旦定了,树就定了,我们需要将“树”的概念抽象掉,唯一核心的就是一个区间对应2个子树和一个根节点!!!

3、对于任意一个区间[L, R],一定是将其划分成2个区间,分别对应最终根节点的左右子树。而根节点的值就是两个区间各自的最大值乘积。

4、对于根节点的子树中非叶子结点的累加值,其实就是在递归子问题中求得了(也可以认为是状态转移方程,因为记忆化搜索和DP本来就是一一对应的)

https://leetcode.cn/problems/minimum-cost-tree-from-leaf-values/solution/qu-jian-dp-dong-tai-gui-hua-die-dai-xie-g4jac/

class Solution {public int mctFromLeafValues(int[] arr) {//区间dp://先计算每个区间内的最大值,用于计算每个非叶子节点的值//分成左右两个子树,得到两个子树中的非叶子节点的和的最小值,相加再加上当前树的root结点的值(上面得到的每个区间的最大值可以计算得到)int n = arr.length;// 预处理区间最大值,这样可以O(1) 的获取每个区间的最大值int[][] g = new int[n][n];for(int i = 0; i < n; i++)for(int j = 0; j < n; j++)for(int k = i; k <= j; k++)g[i][j] = Math.max(g[i][j], arr[k]);int[][] f = new int[n][n];// 区间DPfor(int len = 1; len <= n; len++){ // 枚举区间长度for(int i = 0; i + len - 1 < n; i++){ // 枚举区间起点int j = i + len - 1; // 区间终点f[i][j] = Integer.MAX_VALUE; // 因为求区间最小值,初始化为infif(len == 1) f[i][j] = 0;else{for(int k = i; k < j; k++)f[i][j] = Math.min(f[i][j], f[i][k] + f[k+1][j] + g[i][k] * g[k+1][j]);}}}return f[0][n-1];}
}

单调栈

https://leetcode.cn/problems/minimum-cost-tree-from-leaf-values/solution/1130-cchao-100de-dan-diao-zhan-tan-xin-j-7zwh/

贪心的单调栈解法

  • 最优情况:其实就是严格有序的,从小到大来乘然后累加,对应情况就是类似[4,3,2,1]
  • 指导原则:严格按照arr的顺序下,每次总是用乘积最小两个数一起乘
  • 使用一个单调递减的栈来实现局部有序
    • 不满足有序:一旦发现当前元素大于栈顶,则弹出栈顶元素,(这个元素作为叶子节点,必须要做乘法)
    • 此时需要考虑是新的栈顶 和 当前元素 的最小值 去乘,乘的结果会做累加
    • 弹出全部比它小的元素后,插入新的元素到栈顶
  • 坑:最后栈里可能存有排序好的数字(本质就是最优的解),需要依次弹出一个并累加乘积
  • 整个过程中累加结果就是结果+
class Solution {public int mctFromLeafValues(int[] arr) {// 维护一个单调递减的栈Deque<Integer> dq = new ArrayDeque<>();// 预先插入一个极大值,后续无需判断边缘情况,如s为空dq.addLast(Integer.MAX_VALUE);int n = arr.length;int res = 0;for(int num : arr){while(num > dq.peekLast()){int cur = dq.pollLast();// 这里要考虑可能接下来栈顶数字比arr[i]还要小,我们需要用这个更小数字来乘res += cur * Math.min(dq.peekLast(), num);}dq.addLast(num);}// 最后弹出剩余元素(除了预先插入 INT_MAX,所以最小是3才考虑)while(dq.size() >= 3){int cur = dq.pollLast();res += cur * dq.peekLast();}return res;}
}

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

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

相关文章

人工智能粒子群优化三大算法

粒子群优化是以邻域原理&#xff08;neighborhood principle&#xff09;为基础进行操作的&#xff0c;该原理来源于社会网络结构研究中。驱动粒子群优化的特性是社会交互作用。群中的个体&#xff08;粒子&#xff09;相互学习&#xff0c;而且基于获得的知识移动到更相似于它…

Golang每日一练(leetDay0082) 用队列实现栈、用栈实现队列

目录 225. 用队列实现栈 Implement Stack Using Queues &#x1f31f; 232. 用栈实现队列 Implement Queue Using Stacks &#x1f31f; &#x1f31f; 每日一练刷题专栏 &#x1f31f; Rust每日一练 专栏 Golang每日一练 专栏 Python每日一练 专栏 C/C每日一练 专栏 …

PS07海报截剪和切片(标尺使用),PS08图框工具(剪贴蒙版),PS09吸管工具组(颜色取样)

PS07海报截剪和切片&#xff08;标尺使用&#xff09; PS08图框工具&#xff08;剪贴蒙版&#xff09;PS09吸管工具组&#xff08;颜色取样&#xff09;

ps制作太极图

最终效果&#xff1a; 操作步骤&#xff1a; (1)、 新建文件-800*800px&#xff0c;打开标尺&#xff0c;新建参考线、得到中心点。 ctrlr 打开标尺&#xff0c; 学会 拉 标尺线&#xff0c; 拉出两条标尺线&#xff0c;让其水平、垂直相交。 (2)、 椭圆选框-以中心点绘制正圆…

用ps制作太极图

操作步骤&#xff1a; (1)、 新建文件-800*800px&#xff0c;打开标尺&#xff0c;新建参考线、得到中心点。 ctrlr 打开标尺&#xff0c; 学会 拉 标尺线&#xff0c; 拉出两条标尺线&#xff0c;让其水平、垂直相交。 (2)、 椭圆选框-以中心点绘制正圆&#xff08;按AltShi…

ps中怎样测量标尺线之间的距离及怎样切换距离单位

2019独角兽企业重金招聘Python工程师标准>>> 首先说一下&#xff0c;我用ps还不是很熟练&#xff0c;所以都是初级的问题&#xff0c;希望各位ps大神莫喷~~首先说一下怎么找到标尺呢&#xff1f;打开ps后&#xff0c;最上面有一个视图&#xff0c;点击后将标尺选项前…

前端ps基本操作

在还原设计时,我们需要使用 photoshop打开sd格式的设计,作为的工程师,我们不要太多的ps技巧,只需要了 一些简单的基本操作即可 1、alt 滚轮缩放放图片 2、空格鼠标左健拖动图片 3、shiftm切换选取工具,使用鼠标左键选择,ctrld可以取消选取 4、F8查看信息,可以查看选取内容的…

2.ps基本操作

提示&#xff1a;文章写完后&#xff0c;ps基本操作。 1、ps安装包 阿里云盘分享https://www.aliyundrive.com/s/XWxksTdanpW获取码&#xff1a;mp74 ps安装包 https://www.aliyundrive.com/s/XWxksTdanpW 提取码: mp74 点击链接保存&#xff0c;或者复制本段内容&#xff0c;打…

photoshop标尺工具_RulersGuides.js – Web上的Photoshop样式标尺和指南

关于Photoshop的最好的事情之一是其易于使用的指导线 &#xff0c;可以从标尺上拉出。 这些指南可以使放置物品和正确放置天平时的设计过程变得更加容易。 令我们非常高兴的是&#xff0c; 马克罗利奇 &#xff08; Mark Rolich &#xff09;实现了此特殊功能&#xff0c;以便…

chatgpt赋能python:Python中输入的全面介绍

Python中输入的全面介绍 在Python编程语言中&#xff0c;输入是指程序要求用户将内容输入到程序中进行处理。输入函数为input()&#xff0c;它允许用户直接在程序中输入数据。本文将全面介绍Python中输入的用法&#xff0c;包括如何使用input()函数、如何进行输入的类型转换以…

软件测试总结

软件生命周期(SDLC)的六个阶段 1、问题的定义及规划 此阶段是软件开发方与需求方共同讨论&#xff0c;主要确定软件的开发目标及其可行性。 2、需求分析 在确定软件开发可行的情况下&#xff0c;对软件需要实现的各个功能进行详细分析。需求分析阶段是一个很重要…

pr片头、滚动与开放式字幕制作

pr字幕与滚动字幕制作&#xff1a; 片头字幕&#xff1a;点击文字工具&#xff08;Ctrl鼠标左键 打点&#xff09; 开放式字幕&#xff1a;新建序列-字幕 滚动字幕&#xff1a;旧版标题-滚动选项

ckeditor动态显示隐藏工具栏指定的按钮

客户说工具栏太复杂了&#xff0c;但是有时候又能用到&#xff0c;所以给了个需求&#xff0c;做一个按钮能实现显示或隐藏按钮 好吧&#xff0c;客户是上帝&#xff0c;开搞 思路&#xff1a;ckeditor添加一个自定义按钮&#xff0c;里面方法实现display&#xff1a;none样式…

金蝶服务器如何显示在任务栏,报表窗口看不见工具栏界面怎么办?

有的用户在打开金蝶KIS记账王会计报表后&#xff0c;竟然发现看不到保存、预览、打印等工具栏界面&#xff0c;这些工具与应用账簿报表数据息息相关&#xff0c;没有这些工具的话将大大想想使用效率。但是请放心&#xff0c;工具栏界面消失不是无法解决的棘手问题&#xff0c;下…

Linux(Ubuntu)菜单栏(工具栏)隐藏了,怎么显示出来

最近有捡起了LInux&#xff0c;换了新版本&#xff0c;有好多设置有点儿生疏 在使用的过程中&#xff0c;对一些比较典型的问题或者方法&#xff0c;进行一个总结&#xff0c;方便后面查看&#xff0c;也给各位道友一个参考。 其实这个问题也比较尴尬&#xff0c;如下图&…

计算机桌面工具栏,win7电脑计算机界面菜单工具栏不见了怎么办?

因为在咱们的windows系统中&#xff0c;具有很多的工具栏配置&#xff0c;咱们很多界面的窗口上方都有这样的一个工具栏&#xff0c;大家不妨随意的在自己的win7电脑中找到一个文件夹&#xff0c;之后咱们双击打开&#xff0c;在打开的文件夹窗口上方&#xff0c;咱们就可以看到…

word2007工具栏隐藏了怎样能一直显示?

1、首先在电脑中打开word文档&#xff0c;可以发现“功能区”被自动隐藏了&#xff0c;如下图所示。 2、这时需要点击左上角的开始选项卡&#xff0c;如下图所示。 3、然后在打开的开始菜单中&#xff0c;A下方的横杠&#xff0c;选择单击取消勾选“折叠功能区”。 4、这样“功…

easyUI dataGrid 隐藏分页工具栏 隐藏表头

一.方法1&#xff08;不推荐&#xff09; 适应以下需求&#xff1a; 1.当表格没有数据时&#xff0c;把datagrid隐藏;有数据的时候显示 2.表格不分页&#xff0c;无需显示分页栏 3.datagrid的高度由内容撑开&#xff08;固定高度&#xff0c;无数据时显示空白也可&#xff…

PowerDesigner工具栏消失恢复

PowerDesigner一键导入数据库所有表并画数据模型图 五分钟学会PowerDesigner创建概念数据模型 PowerDesigner设计的pdm模型导出超清图片 PowerDesigner工具栏消失恢复 目录 一、工具栏 二、点击工具-自定义菜单和工具栏 三、选择Palette即可 一、工具栏 不小心点到工具栏右上角…