列表

详情


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

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

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

 

示例:

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

    24            24
   /  \          /  \
  12   4        6    8
 /  \               / \
6    2             2   4

 

提示:

原站题解

去查看

上次编辑到这里,代码来自缓存 点击恢复默认模板
class Solution { public: int mctFromLeafValues(vector<int>& arr) { } };

javascript 解法, 执行用时: 80 ms, 内存消耗: 44.6 MB, 提交时间: 2022-11-28 14:33:33

/**
 * @param {number[]} arr
 * @return {number}
 */
/**
 * dp[i][j] 表示将 arr[i...j] 合并之后所得的最小乘积之和。
 * dp[0][len] 就是最终答案。
 */
 var mctFromLeafValues = function(arr) {
	const n = arr.length;
	const dp = new Array(n).fill(0).map(() => new Array(n).fill(0));
	const maxVal = new Array(n).fill(0).map(() => new Array(n).fill(0));

	for(let i = 0; i < n; i++) {
		maxVal[i][i] = arr[i];
		for(let j = i + 1; j < n; j++) {
			maxVal[i][j] = Math.max(maxVal[i][j-1], arr[j]);
		}
	}

	for(let len = 1; len < n; len++) {
		for(let i = 0; i + len < n; i++) {
			dp[i][i+len] = Number.MAX_SAFE_INTEGER;
			for(let k = i; k < i + len; k++) {
				dp[i][i+len] = Math.min(dp[i][i+len], dp[i][k] + dp[k+1][i+len] + maxVal[i][k] * maxVal[k+1][i+len]);
			}
		}
	}

	return dp[0][n-1];
};

javascript 解法, 执行用时: 52 ms, 内存消耗: 41.1 MB, 提交时间: 2022-11-28 14:32:42

/**
 * @param {number[]} arr
 * @return {number}
 */
var mctFromLeafValues = function(arr) {
	const n = arr.length;
	const stack = [];
	let res = 0;

	for(let i = 0; i < n; i++) {
		while(stack.length && (stack[stack.length-1] <= arr[i] || i === n-1)) {
			const bottom = stack.pop();
			if(stack.length) {
				res += Math.min(stack[stack.length-1], arr[i]) * bottom;
			} else {
				res += bottom * arr[i];
			}
			arr[i] = Math.max(bottom, arr[i]);
		}
		stack.push(arr[i]);
	}

	return res;
};

cpp 解法, 执行用时: 0 ms, 内存消耗: 8 MB, 提交时间: 2022-11-28 14:31:59

class Solution {
public:
    int mctFromLeafValues(vector<int>& arr) {
        int ans=0,pos=0;
        while(arr.size()>1)
        {
            int Min=INT_MAX;
            for(int i=0;i<arr.size()-1;++i)
            {
                if(Min>arr[i]*arr[i+1])//找到最小的两个值
                {
                    Min=arr[i]*arr[i+1];
                    pos=arr[i]<arr[i+1]?i:i+1;
                }
            }
            ans+=Min;
            arr.erase(arr.begin()+pos);//删去其中最小的一个
        }
        return ans;
    }
};

python3 解法, 执行用时: 36 ms, 内存消耗: 14.8 MB, 提交时间: 2022-11-28 14:31:19

class Solution:
    def mctFromLeafValues(self, A: List[int]) -> int:
        res, n = 0, len(A)
        stack = [float('inf')]
        for a in A:
            while stack[-1] <= a:
                mid = stack.pop()
                res += mid * min(stack[-1], a)
            stack.append(a)
        while len(stack) > 2:
            res += stack.pop() * stack[-1]
        return res

python3 解法, 执行用时: 128 ms, 内存消耗: 14.9 MB, 提交时间: 2022-11-28 14:30:54

class Solution:
    def mctFromLeafValues(self, arr: List[int]) -> int:
        n = len(arr)
        # 初始值设为最大
        dp = [[float('inf') for _ in range(n)] for _ in range(n)]
        # 初始区间查询最大值设为0
        maxval = [[0 for _ in range(n)] for _ in range(n)]
        # 求区间[i, j]中最大元素
        for i in range(n):
            for j in range(i, n):
                maxval[i][j] = max(arr[i:j + 1])
        # 叶子结点不参与计算
        for i in range(n):
            dp[i][i] = 0
        # 枚举区间长度
        for l in range(1, n):
            # 枚举区间起始点
            for s in range(n - l):
                # 枚举划分两棵子树
                for k in range(s, s + l):
                    dp[s][s + l] = min(dp[s][s + l], dp[s][k] + dp[k + 1][s + l] + maxval[s][k] * maxval[k + 1][s + l])
        return dp[0][n - 1]

java 解法, 执行用时: 1 ms, 内存消耗: 39.2 MB, 提交时间: 2022-11-28 14:29:43

class Solution {
    public int mctFromLeafValues(int[] arr) {
        Stack<Integer> st = new Stack();
        st.push(Integer.MAX_VALUE);
        int mct = 0;
        for (int i = 0; i < arr.length; i++) {
            while (arr[i] >= st.peek()) {
                mct += st.pop() * Math.min(st.peek(), arr[i]);
            }
            st.push(arr[i]);
        }
        while (st.size() > 2) {
            mct += st.pop() * st.peek();
        }
        return mct;
    }
}

上一题