树型dp套路
树型dp套路的第一步:
以某个节点X为头节点的子树中,分析答案有哪些可能性,并且这种分析是以X的左子树、X的右子树和X整棵树的角度来考虑可能性的
注意:先只按最头结点分析就可以,这样分析不会乱,不要想下面的节点会怎样
树形dp套路第二步:
根据第一步的可能性分析,列出所有需要的信息
树形dp套路第三步:
合并第二步的信息,对左树和右树提出同样的要求,并写出信息结构
树形dp套路第四步:
设计递归函数,递归函数是处理以X为头节点的情况下的答案。 包括设计递归的basecase,默认直接得到左树和右树的所有信息,以及把可能性做整合,并且要返回第三步的信息结构这四个小步骤
补充题目1
叉树节点间的最大距离问题
从二叉树的节点a出发,可以向上或者向下走,但沿途的节点只能经过一次,到达节点b时路 径上的节点个数叫作a到b的距离,那么二叉树任何两个节点之间都有距离,求整棵树上的最大距离。
相关分析
相关代码
//定义结点结构
public static class Node{
public int value;
public Node left;
public Node right;
public Node(int data){
this.value = data;
}
}
//定义返回值结构,因为按照头结点进行分开,得出了结论,需要返回
//最大距离,和对应的高度
public static class ReturnType{
public int maxDistance;
public int h;
public ReturnType(int m, int h){
this.maxDistance = m;
this.h = h;
}
}
public static int maxDistance(Node head){
int[] record = new int[1];
// return posOrder(head, record);
return process(head).maxDistance;
}
//不用返回值类型结构的时候
public static int posOrder(Node head, int[] record) {
if (head == null){
record[0] = 0;
return 0;
}
//返回左边的最大值
int lmax = posOrder(head.left, record);
//记录最大高度
int maxfromLeft = record[0];
//返回右边的最大值
int rmax = posOrder(head.right, record);
//记录最大高度
int maxFromRight = record[0];
//如果带上头结点是最大高度的情况下的最大距离
int curNodeMax = maxfromLeft + maxFromRight + 1;
//record[0]的产生
record[0] = Math.max(maxfromLeft, maxFromRight) + 1;
return Math.max(Math.max(lmax, rmax), curNodeMax);
}
//用返回值结构的时候
public static ReturnType process(Node head){
if (head == null){
return new ReturnType(0,0);
}
ReturnType leftReturnType = process(head.left);
ReturnType rightReturnType = process(head.right);
int includeHeadDistance = leftReturnType.h + 1 + rightReturnType.h;
int p1 = leftReturnType.maxDistance;
int p2 = rightReturnType.maxDistance;
int resultDistance = Math.max(Math.max(p1, p2), includeHeadDistance);
return new ReturnType(resultDistance,Math.max(leftReturnType.h, rightReturnType.h) + 1);
}
public static void main(String[] args){
Node head1 = new Node(1);
head1.left = new Node(2);
head1.right = new Node(3);
head1.left.left = new Node(4);
head1.left.right = new Node(5);
head1.right.left = new Node(6);
head1.right.right = new Node(7);
head1.left.left.left = new Node(8);
head1.right.left.right = new Node(9);
System.out.println(maxDistance(head1));
}
补充题目2
派对的最大快乐值
相关分析
相关代码
//定义结点结构
public static class Employee{
public int happy;//这名员工可以带来的快乐值
public List<Employee> nexts;//这名员工有哪些直接下级
}
//定义返回值结构,因为按照头结点进行分开,得出了结论,需要返回
//节点不来最大值,节点来的最大值
public static class ReturnType{
public int laiMaxHappy;
public int buMaxHappy;
public ReturnType(int lai, int bu){
this.laiMaxHappy = lai;
this.buMaxHappy = bu;
}
}
//主函数
public static int maxHappy(Employee boss){
ReturnType headReturnType = process(boss);
return Math.max(headReturnType.laiMaxHappy, headReturnType.buMaxHappy);
}
//用返回值结构的时候
public static ReturnType process(Employee x){
if (x.nexts.isEmpty()){//x是基层员工的时候
return new ReturnType(x.happy,0);
}
int lai = x.happy;
int bu = 0;
for (Employee next : x.nexts){
ReturnType nextReturnType = process(next);
//当x来的时候,我的底层员工只能不来
lai += nextReturnType.buMaxHappy;
//当x不来的时候,我的底层员工可以选择来,也可以选择不来,取最大
bu += Math.max(nextReturnType.laiMaxHappy, nextReturnType.buMaxHappy);
}
return new ReturnType(lai, bu);
}