51
51
52
52
** 方法一:记忆化搜索**
53
53
54
- 根据题目描述,数组 $arr$ 中的值与树的中序遍历中每个叶节点的值一一对应,因此可以将数组 $arr$ 中的值看作是树的叶节点,我们可以将数组划分为左右两个子数组, 分别对应树的左右子树,递归地每个子树的所有非叶子节点的值的最小可能总和 。
54
+ 根据题目描述,数组 $arr$ 中的值与树的中序遍历中每个叶节点的值一一对应,我们可以将数组划分为左右两个非空子数组, 分别对应树的左右子树,递归地求解每个子树的所有非叶节点的值的最小可能总和 。
55
55
56
- 我们设计一个函数 $dfs(i, j)$,表示数组 $arr$ 中下标范围 $[ i, j] $ 内的所有叶节点的值的最小可能总和 ,那么答案就是 $dfs(0, n - 1)$,其中 $n$ 为数组 $arr$ 的长度。
56
+ 我们设计一个函数 $dfs(i, j)$,表示数组 $arr$ 中下标范围 $[ i, j] $ 内的所有非叶节点的值的最小可能总和 ,那么答案就是 $dfs(0, n - 1)$,其中 $n$ 为数组 $arr$ 的长度。
57
57
58
58
函数 $dfs(i, j)$ 的计算过程如下:
59
59
60
- - 如果 $i = j$,说明数组 $arr$ 中只有一个元素,因此 $dfs(i, j) = 0$。
61
- - 否则,我们枚举 $k \in [ i, j - 1] $,将数组 $arr$ 划分为两个子数组 $arr[ i \cdots k] $ 和 $arr[ k + 1 \cdots j] $,对于每个 $k$,我们计算 $dfs(i, k)$ 和 $dfs(k + 1, j)$,其中 $dfs(i, k)$ 表示数组 $arr$ 中下标范围 $[ i, k] $ 内的所有叶节点的值的最小可能总和 ,而 $dfs(k + 1, j)$ 表示数组 $arr$ 中下标范围 $[ k + 1, j] $ 内的所有叶节点的值的最小可能总和 ,那么 $dfs(i, j) = \min_ {i \leq k < j} \{ dfs(i, k) + dfs(k + 1, j) + \max_ {i \leq t \leq k} \{ arr[ t] \} \max_ {k < t \leq j} \{ arr[ t] \}\} $。
60
+ - 如果 $i = j$,说明数组 $arr[ i..j ] $ 中只有一个元素,因此 $dfs(i, j) = 0$。
61
+ - 否则,我们枚举 $k \in [ i, j - 1] $,将数组 $arr$ 划分为两个子数组 $arr[ i \cdots k] $ 和 $arr[ k + 1 \cdots j] $,对于每个 $k$,我们递归计算 $dfs(i, k)$ 和 $dfs(k + 1, j)$,其中 $dfs(i, k)$ 表示数组 $arr$ 中下标范围 $[ i, k] $ 内的所有非叶节点的值的最小可能总和 ,而 $dfs(k + 1, j)$ 表示数组 $arr$ 中下标范围 $[ k + 1, j] $ 内的所有非叶节点的值的最小可能总和 ,那么 $dfs(i, j) = \min_ {i \leq k < j} \{ dfs(i, k) + dfs(k + 1, j) + \max_ {i \leq t \leq k} \{ arr[ t] \} \max_ {k < t \leq j} \{ arr[ t] \}\} $。
62
62
63
- 上述递归过程中,我们可以使用记忆化搜索的方法进行优化,避免重复计算。
63
+ 综上所述,我们可以得到:
64
+
65
+ $$
66
+ dfs(i, j) = \begin{cases}
67
+ 0, & \text{if } i = j \\
68
+ \min_{i \leq k < j} \{dfs(i, k) + dfs(k + 1, j) + \max_{i \leq t \leq k} \{arr[t]\} \max_{k < t \leq j} \{arr[t]\}\}, & \text{if } i < j
69
+ \end{cases}
70
+ $$
71
+
72
+ 上述递归过程中,我们可以使用记忆化搜索的方法,避免重复计算。
64
73
65
74
最后,我们返回 $dfs(0, n - 1)$ 即可。
66
75
70
79
71
80
我们可以将方法一中的记忆化搜索改为动态规划的方式进行求解。
72
81
73
- 定义 $f[ i] [ j ] $ 表示数组 $arr$ 中下标范围 $[ i, j] $ 内的所有叶节点的值的最小可能总和,而 $g[ i] [ j ] $ 表示数组 $arr$ 中下标范围 $[ i, j] $ 内的所有叶节点的最大值,那么 $f[ i] [ j ] = \min_ {i \leq k < j} \{ f[ i] [ k ] + f[ k + 1] [ j ] + g[ i] [ k ] \cdot g[ k + 1] [ j ] \} $,其中 $g[ i] [ j ] = \max_ {i \leq k \leq j} \{ arr[ k] \} $。
82
+ 定义 $f[ i] [ j ] $ 表示数组 $arr$ 中下标范围 $[ i, j] $ 内的所有非叶节点的值的最小可能总和,而 $g[ i] [ j ] $ 表示数组 $arr$ 中下标范围 $[ i, j] $ 内的所有叶节点的最大值,那么状态转移方程为:
83
+
84
+ $$
85
+ f[i][j] = \begin{cases}
86
+ 0, & \text{if } i = j \\
87
+ \min_{i \leq k < j} \{f[i][k] + f[k + 1][j] + g[i][k] \cdot g[k + 1][j]\}, & \text{if } i < j
88
+ \end{cases}
89
+ $$
74
90
75
91
最后,我们返回 $f[ 0] [ n - 1 ] $ 即可。
76
92
86
102
class Solution :
87
103
def mctFromLeafValues (self , arr : List[int ]) -> int :
88
104
@cache
89
- def dfs (i : int , j : int ):
105
+ def dfs (i : int , j : int ) -> Tuple :
90
106
if i == j:
91
107
return 0 , arr[i]
92
108
s, mx = inf, - 1
@@ -105,18 +121,32 @@ class Solution:
105
121
``` python
106
122
class Solution :
107
123
def mctFromLeafValues (self , arr : List[int ]) -> int :
124
+ @cache
125
+ def dfs (i : int , j : int ) -> int :
126
+ if i == j:
127
+ return 0
128
+ return min (dfs(i, k) + dfs(k + 1 , j) + g[i][k] * g[k + 1 ][j] for k in range (i, j))
129
+
108
130
n = len (arr)
109
- f = [[0 ] * n for _ in range (n)]
110
131
g = [[0 ] * n for _ in range (n)]
111
- for i in range (n):
132
+ for i in range (n - 1 , - 1 , - 1 ):
112
133
g[i][i] = arr[i]
113
134
for j in range (i + 1 , n):
114
135
g[i][j] = max (g[i][j - 1 ], arr[j])
136
+ return dfs(0 , n - 1 )
137
+ ```
138
+
139
+ ``` python
140
+ class Solution :
141
+ def mctFromLeafValues (self , arr : List[int ]) -> int :
142
+ n = len (arr)
143
+ f = [[0 ] * n for _ in range (n)]
144
+ g = [[0 ] * n for _ in range (n)]
115
145
for i in range (n - 1 , - 1 , - 1 ):
146
+ g[i][i] = arr[i]
116
147
for j in range (i + 1 , n):
117
- f[i][j] = inf
118
- for k in range (i, j):
119
- f[i][j] = min (f[i][j], f[i][k] + f[k + 1 ][j] + g[i][k] * g[k + 1 ][j])
148
+ g[i][j] = max (g[i][j - 1 ], arr[j])
149
+ f[i][j] = min (f[i][k] + f[k + 1 ][j] + g[i][k] * g[k + 1 ][j] for k in range (i, j))
120
150
return f[0 ][n - 1 ]
121
151
```
122
152
@@ -133,9 +163,9 @@ class Solution {
133
163
int n = arr. length;
134
164
f = new Integer [n][n];
135
165
g = new int [n][n];
136
- for (int i = 0 ; i < n; i ++ ) {
166
+ for (int i = n - 1 ; i >= 0 ; -- i ) {
137
167
g[i][i] = arr[i];
138
- for (int j = i + 1 ; j < n; j ++ ) {
168
+ for (int j = i + 1 ; j < n; ++ j ) {
139
169
g[i][j] = Math . max(g[i][j - 1 ], arr[j]);
140
170
}
141
171
}
@@ -164,14 +194,10 @@ class Solution {
164
194
int n = arr. length;
165
195
int [][] f = new int [n][n];
166
196
int [][] g = new int [n][n];
167
- for (int i = 0 ; i < n; ++ i) {
197
+ for (int i = n - 1 ; i >= 0 ; -- i) {
168
198
g[i][i] = arr[i];
169
199
for (int j = i + 1 ; j < n; ++ j) {
170
200
g[i][j] = Math . max(g[i][j - 1 ], arr[j]);
171
- }
172
- }
173
- for (int i = n - 2 ; i >= 0 ; -- i) {
174
- for (int j = i + 1 ; j < n; ++ j) {
175
201
f[i][j] = 1 << 30 ;
176
202
for (int k = i; k < j; ++ k) {
177
203
f[i][j] = Math . min(f[i][j], f[i][k] + f[k + 1 ][j] + g[i][k] * g[k + 1 ][j]);
@@ -193,7 +219,7 @@ public:
193
219
int f[ n] [ n ] ;
194
220
int g[ n] [ n ] ;
195
221
memset(f, 0, sizeof(f));
196
- for (int i = 0; i < n; ++ i) {
222
+ for (int i = n - 1; ~ i; -- i) {
197
223
g[ i] [ i ] = arr[ i] ;
198
224
for (int j = i + 1; j < n; ++j) {
199
225
g[ i] [ j ] = max(g[ i] [ j - 1 ] , arr[ j] );
@@ -225,14 +251,10 @@ public:
225
251
int f[n][n];
226
252
int g[n][n];
227
253
memset(f, 0, sizeof(f));
228
- for (int i = 0; i < n; ++ i) {
254
+ for (int i = n - 1; ~i; -- i) {
229
255
g[i][i] = arr[i];
230
256
for (int j = i + 1; j < n; ++j) {
231
257
g[i][j] = max(g[i][j - 1], arr[j]);
232
- }
233
- }
234
- for (int i = n - 2; ~i; --i) {
235
- for (int j = i + 1; j < n; ++j) {
236
258
f[i][j] = 1 << 30;
237
259
for (int k = i; k < j; ++k) {
238
260
f[i][j] = min(f[i][j], f[i][k] + f[k + 1][j] + g[i][k] * g[k + 1][j]);
@@ -299,13 +321,11 @@ func mctFromLeafValues(arr []int) int {
299
321
for i := range g {
300
322
f[i] = make ([]int , n)
301
323
g[i] = make ([]int , n)
324
+ }
325
+ for i := n - 1 ; i >= 0 ; i-- {
302
326
g[i][i] = arr[i]
303
327
for j := i + 1 ; j < n; j++ {
304
328
g[i][j] = max (g[i][j-1 ], arr[j])
305
- }
306
- }
307
- for i := n - 2 ; i >= 0 ; i-- {
308
- for j := i + 1 ; j < n; j++ {
309
329
f[i][j] = 1 << 30
310
330
for k := i; k < j; k++ {
311
331
f[i][j] = min (f[i][j], f[i][k]+f[k+1 ][j]+g[i][k]*g[k+1 ][j])
@@ -330,6 +350,61 @@ func min(a, b int) int {
330
350
}
331
351
```
332
352
353
+ ### ** TypeScript**
354
+
355
+ ``` ts
356
+ function mctFromLeafValues(arr : number []): number {
357
+ const n = arr .length ;
358
+ const f: number [][] = new Array (n ).fill (0 ).map (() => new Array (n ).fill (0 ));
359
+ const g: number [][] = new Array (n ).fill (0 ).map (() => new Array (n ).fill (0 ));
360
+ for (let i = n - 1 ; i >= 0 ; -- i ) {
361
+ g [i ][i ] = arr [i ];
362
+ for (let j = i + 1 ; j < n ; ++ j ) {
363
+ g [i ][j ] = Math .max (g [i ][j - 1 ], arr [j ]);
364
+ }
365
+ }
366
+ const dfs = (i : number , j : number ): number => {
367
+ if (i === j ) {
368
+ return 0 ;
369
+ }
370
+ if (f [i ][j ] > 0 ) {
371
+ return f [i ][j ];
372
+ }
373
+ let ans = 1 << 30 ;
374
+ for (let k = i ; k < j ; ++ k ) {
375
+ ans = Math .min (
376
+ ans ,
377
+ dfs (i , k ) + dfs (k + 1 , j ) + g [i ][k ] * g [k + 1 ][j ],
378
+ );
379
+ }
380
+ return (f [i ][j ] = ans );
381
+ };
382
+ return dfs (0 , n - 1 );
383
+ }
384
+ ```
385
+
386
+ ``` ts
387
+ function mctFromLeafValues(arr : number []): number {
388
+ const n = arr .length ;
389
+ const f: number [][] = new Array (n ).fill (0 ).map (() => new Array (n ).fill (0 ));
390
+ const g: number [][] = new Array (n ).fill (0 ).map (() => new Array (n ).fill (0 ));
391
+ for (let i = n - 1 ; i >= 0 ; -- i ) {
392
+ g [i ][i ] = arr [i ];
393
+ for (let j = i + 1 ; j < n ; ++ j ) {
394
+ g [i ][j ] = Math .max (g [i ][j - 1 ], arr [j ]);
395
+ f [i ][j ] = 1 << 30 ;
396
+ for (let k = i ; k < j ; ++ k ) {
397
+ f [i ][j ] = Math .min (
398
+ f [i ][j ],
399
+ f [i ][k ] + f [k + 1 ][j ] + g [i ][k ] * g [k + 1 ][j ],
400
+ );
401
+ }
402
+ }
403
+ }
404
+ return f [0 ][n - 1 ];
405
+ }
406
+ ```
407
+
333
408
### ** ...**
334
409
335
410
```
0 commit comments