LC.P1130[叶值的最小代价生成树]

方法一:记忆化搜索

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class Solution {
int[][] cache;
int[][] g;

public int mctFromLeafValues(int[] arr) {
int n = arr.length;
cache = new int[n][n];
g = new int[n][n];
for (int i = n - 1; i >= 0; --i) {
g[i][i] = arr[i];
for (int j = i + 1; j < n; ++j) {
g[i][j] = Math.max(g[i][j - 1], arr[j]);
}
}
return dfs(0, n - 1);
}

private int dfs(int i, int j) {
if (i == j) return 0;
if (cache[i][j] != 0) return cache[i][j];
int ans = Integer.MAX_VALUE;
for (int k = i; k < j; ++k) {
ans = Math.min(ans, dfs(i, k) + dfs(k + 1, j) + g[i][k] * g[k + 1][j]);
}
return cache[i][j] = ans;
}
}
  • 时间复杂度:$O(n^3)$
  • 空间复杂度:$O(n^2)$

方法二:动态规划

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Solution {
public int mctFromLeafValues(int[] arr) {
int n = arr.length;
int[][] f = new int[n][n];
int[][] g = new int[n][n];
for (int i = n - 1; i >= 0; --i) {
g[i][i] = arr[i];
for (int j = i + 1; j < n; ++j) {
g[i][j] = Math.max(g[i][j - 1], arr[j]);
f[i][j] = Integer.MAX_VALUE;
for (int k = i; k < j; ++k) {
f[i][j] = Math.min(f[i][j], f[i][k] + f[k + 1][j] + g[i][k] * g[k + 1][j]);
}
}
}
return f[0][n - 1];
}
}
  • 时间复杂度:$O(n^3)$
  • 空间复杂度:$O(n^2)$