给你一个正整数数组 arr,考虑所有满足以下条件的二叉树:
在所有这样的二叉树中,返回每个非叶节点的值的最小可能总和。
这个和的值是一个 32 位整数。
示例:
输入:arr = [6,2,4]
输出:32
解释:
有两种可能的树,
第一种的非叶节点的总和为 36,
第二种非叶节点的总和为 32。
24 24
/ \ / \
12 4 6 8
/ \ / \
6 2 2 4
提示:
2 <= arr.length <= 40
1 <= arr[i] <= 15
答案保证是一个 32 位带符号整数,即小于 2^31。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/minimum-cost-tree-from-leaf-values
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
类似题目:
LeetCode 1039. 多边形三角剖分的最低得分(区间DP)
class Solution {
public:
int mctFromLeafValues(vector<int>& arr) {
int n = arr.size();
vector<vector<pair<int, int>>> dp(n, vector<pair<int, int>>(n, {
INT_MAX, 0}));
//dp[i][j] 表示区间 [i,j] 的 {非叶节点的min(sum), 区间的最大叶子节点值}
for(int i = 0; i < n; i++) //初始化
{
dp[i][i].first = 0;//sum
dp[i][i].second = arr[i];//maxval
}
for(int len = 1; len < n; ++len)//区间长度
{
for(int i = 0, j; i+len < n; ++i)//左端点
{
j = i+len;//右端点
for(int k = i; k < j; ++k)//枚举中间端点
{
if(dp[i][j].first > dp[i][k].first+dp[k+1][j].first+dp[i][k].second*dp[k+1][j].second)
{
//左区间的和 + 右区间的和 + 当前节点的val = maxL*maxR
dp[i][j].first = dp[i][k].first+dp[k+1][j].first+dp[i][k].second*dp[k+1][j].second;
//用更小的sum更新
dp[i][j].second = max(dp[i][k].second, dp[k+1][j].second);
// 更新区间的最大叶节点值
}
}
}
}
return dp[0][n-1].first;
}
};
16 ms 9.3 MB
class Solution {
public:
int mctFromLeafValues(vector<int>& arr) {
int n = arr.size(), tp, ans = 0;
stack<int> stk;
stk.push(INT_MAX);
for(int a : arr)
{
while(a >= stk.top())//单调递减栈,不满足了,弹栈
{
tp = stk.top();
stk.pop();
ans += tp*min(a, stk.top());
}
stk.push(a);
}
while(stk.size() > 2)
{
tp = stk.top();
stk.pop();
ans += tp*stk.top();
}
return ans;
}
};
0 ms 8.7 MB
我的CSDN博客地址 https://michael.blog.csdn.net/
长按或扫码关注我的公众号(Michael阿明),一起加油、一起学习进步!