1. 程式人生 > 其它 >leecode.1130. 葉值的最小代價生成樹

leecode.1130. 葉值的最小代價生成樹

技術標籤:leecode-動態規劃

題目

葉值的最小代價生成樹

給你一個正整數陣列 arr,考慮所有滿足以下條件的二叉樹:

每個節點都有 0 個或是 2 個子節點。
陣列 arr 中的值與樹的中序遍歷中每個葉節點的值一一對應。(知識回顧:如果一個節點有 0 個子節點,那麼該節點為葉節點。)
每個非葉節點的值等於其左子樹和右子樹中葉節點的最大值的乘積。
在所有這樣的二叉樹中,返回每個非葉節點的值的最小可能總和。這個和的值是一個 32 位整數。

輸入:arr = [6,2,4]
輸出:32
解釋:
有兩種可能的樹,第一種的非葉節點的總和為 36,第二種非葉節點的總和為 32。

在這裡插入圖片描述

思路分析

  • 令dp[i][j]為陣列從[i,…,j]的最小值.
  • 當j=i+1,此時只剩兩個數字,此時的答案就是這兩個數值的乘積.
  • 當j>i+1的時候,那麼此時我們可以由j-i個劃分位置,我們依次來遍歷這麼多的位置,然後選取其中的最小結果.為了得到劃分位置左子樹和右子樹的最大值,我們需要使用一個額外的陣列來儲存這些的數值.

程式碼

class Solution {
public:
    int mctFromLeafValues(vector<int>& arr) {
        int n = arr.size();
        vector<vector<int>> dp(n , vector<
int>(n , 0x3f3f3f3f)); vector<vector<int>> maxVal(n , vector<int>(n , 0)); for(int i = n - 1;i >= 0;i--){//選取現有的最大值 dp[i][i] = 0; maxVal[i][i] = arr[i]; for(int j = i + 1;j < n;j++){ maxVal[i][j] = max(maxVal[i +
1][j], maxVal[i][j - 1]); } } for(int i = n - 1;i >= 0;i--){//從右下角的位置開始填寫右上角的矩陣 for(int j = i + 1;j < n;j++){ for(int k = i;k < j;k++){ dp[i][j] = min(dp[i][j], dp[i][k] + dp[k + 1][j] + maxVal[i][k] * maxVal[k + 1][j]); } } } return dp[0][n - 1]; } }; #

陣列例項化的過程

首先,我們這個過程中的maxVal的陣列如下:
6 6 6
0 2 4
0 0 4
其次,在更新右上角的dp矩陣的變化如下所示:
1 2
0 1061109567 1061109567
1061109567 0 8
1061109567 1061109567 0

0 1
0 12 1061109567
1061109567 0 8
1061109567 1061109567 0

0 2
0 12 32
1061109567 0 8
1061109567 1061109567 0
最終的結果就是dp[0][l-1]=32