leecode.1130. 葉值的最小代價生成樹
阿新 • • 發佈:2020-12-22
技術標籤: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