树形dp:我的理解是能按照拓扑序转移就可以算 DP。值得注意的是,这期讲的内容是没有重叠子问题的,所以看上去写个简单递归就解决了,树形 DP 是个约定俗成的叫法。
二叉树树形dp
链接: 543. 二叉树的直径
直接思考原问题(原树)和子问题(左右子树)的关系。
class Solution {
private int ans;
public int diameterOfBinaryTree(TreeNode root) {
dfs(root);
return ans;
}
private int dfs(TreeNode node) {
if (node == null)
return -1; // 下面 +1 后,对于叶子节点就刚好是 0
int lLen = dfs(node.left) + 1; // 左子树最大链长+1
int rLen = dfs(node.right) + 1; // 右子树最大链长+1
ans = Math.max(ans, lLen + rLen); // 两条链拼成路径
return Math.max(lLen, rLen); // 当前子树最大链长
}
}
一般树 树形dp
class Solution {
List<Integer>[] g;
String s;
//最大直径
int ans;
public int longestPath(int[] parent, String s) {
this.s = s;
var n = parent.length;
g = new ArrayList[n];
//g[i] 表示 i节点下所含有的所有子节点。
Arrays.setAll(g, e -> new ArrayList<>());
for (var i = 1; i < n; i++) g[parent[i]].add(i);
dfs(0);
return ans + 1;
}
int dfs(int x) {
//先前遍历的最大子链
var maxLen = 0;
for (var y : g[x]) {
var len = dfs(y) + 1;
if (s.charAt(y) != s.charAt(x)) {
ans = Math.max(ans, maxLen + len);
maxLen = Math.max(maxLen, len);
}
}
return maxLen;
}
}