个人笔记08:一些关于树的问题小结
一、树形DP(动态规划):
(例题)村庄里每户人家作为一个节点,这些节点可以组成一个二叉树。可以在二叉树的节点上供应暖炉,每个暖炉可以为该节点的父节点、自身及其子节点带来温暖。给定一棵二叉树,求使整个村庄都暖和起来至少需要供应多少个暖炉?
(思路)若某棵树的所有节点都被供暖,则称该树被“覆盖”。
假设当前节点为root,左右孩子分别为left,right。要覆盖以root为根的树,有两种情况:
(1)若在root处安放暖炉,则孩子left,right一定也会被供暖。此时,只需要保证left的两棵子树被覆盖,同时保证right的两棵子树也被覆盖。
(2)否则,如果root处不安放暖炉,则除了覆盖root的两棵子树之外,孩子left,right之一必须要安放暖炉,从而保证root会被供暖。
由此,可以分析出,对于每个节点root,需要维护三种类型的状态:
状态A:root必须安放暖炉的情况下,覆盖整棵树需要的暖炉的数目。
状态B:覆盖整棵树需要的暖炉数目,无论root是否安放暖炉。
状态C:覆盖两棵子树需要的暖炉数目,无论节点root本身是否安放暖炉。
由上述定义出发,一定有A≥B≥C。
对于节点root而言,设其左右孩子left,right对应的状态变量分别是(LA,LB,LC)和(RA,RB,RC)。状态转移方程为:
A=LC+RC+1,B=min(A,min(LA+RB,RA+LB))。
对于root而言,如果其某个孩子为空,则不能通过在该孩子处安放暖炉的方式为当前节点供暖。因此,该孩子对应的A置为inf。
最终答案为树的根结点对应的状态变量B。
二、二叉树路径长
(例题)在一个二叉树汇总,每层的节点值赋值方向是交替的,第一层从左到右,第二层从右到左,以此类推。小R想知道,在二叉树中两个节点之间x,y的路径长度是多少。
(思路)本题包括两个部分:由节点值确定节点位置,计算节点间路径长度。
为确定节点位置,首先需要知道其所在层数i(从1开始计)的值。第i层节点值的范围为[pow(2,i-1),pow(2,i)-1]。
若i为奇数,则为从左向右编号,否则为从右向左编号,由此确定了节点位置index。
然后,根据xindex,yindex计算它们间的路径长度。求出xindex和yindex的最近公共祖先lcaindex(lca(rootindex,xindex,yindex)):
1°若当前节点为空(本题不存在此种情形)或当前节点rootindex=xindex或rootindex=yindex,返回rootindex;
2°求Llca=lca(rootindex.left(也即2×rootindex),xindex,yindex),Rlca=lca(rootindex.right(也即2×rootindex+1),xindex,yindex)。
3°若Llca和Rlca都不为空,则返回rootindex。(本题二叉树无穷,故至此结束)
记根结点深度为0。若最终lcaindex为xindex或yindex,则返回x和y的深度之差,否则返回其深度之和。