【左神算法笔记】基础提升-树型dp

题目一:二叉树节点间的最大距离问题

问题:

从二叉树节点a出发,可向上或向下走。沿途节点只能经过一次。到达节点b时路径上的节点个数叫做a到b的距离,那么整棵树任意两节点之间都有距离,求给定树的最大距离

例如:

在这里插入图片描述

a到b的距离为2,d到c的距离为4

分析:树型dp

给定一个树的root,我们要求的最大距离可能有以下几种情况:

1、最大距离内不包括root

那么求root的左子树的最大距离右子树的最大距离

再求两者的max

2、root包含在最终答案中

那么需要找到左子树的最深节点和右子树的最深节点

他们之间的距离就是答案:左子树高度+右子树高度+1

所以我们求上面个值的max

需要的信息:maxDistance(leftTree)、maxDistance(rightTree)、左树高、右树高

    public static int maxDistance(Node root) {
        return process(root).maxDistance;
    }

    // 返回以root为头的整棵树的2个信息
    public static Info process(Node root) {
        if (root==null) return new Info(0,0);
        Info leftInfo = process(root.left);
        Info rightInfo = process(root.right);
        // 3种可能
        int p1 = leftInfo.maxDistance;
        int p2 = rightInfo.maxDistance;
        int p3 = leftInfo.height+rightInfo.height+1;
        // 计算root为根的树的Info
        int maxDistance = Math.max(p1,Math.max(p2,p3));
        int height = Math.max(leftInfo.height,rightInfo.height)+1;
        return new Info(maxDistance,height);
    }

题目二:排队的最大快乐值

问题:

员工信息定义:

class Employee{
    int happy; // 员工给排队带来的快乐值
    List<Employee> subOrdinates; // 这名员工的直接下级
}

可以把所有员工放进一棵多叉树,某节点的子节点就是它的直接下级,头节点是最大的领导,叶节点是咩有下属的基层员工

现在公司办party,我可以给一些员工发请柬,来决定员工来或不来,但有以下规律:

1、某员工来party,则他的直接下级都不来

2、派对的整体快乐值是所有到场员工快乐值的累加

3、我的target是求最大排队快乐值

给定一棵树的root,求最大快乐值

例如:
在这里插入图片描述
那么我只给root和叶节点发请柬即可得max快乐值

再例如:

在这里插入图片描述

我选择第二层的60、100和基层的100、200

分析:

依旧是树型dp问题

给定root,它的最大快乐值有以下几种情况:

1、包括root

加入root有子节点a、b、c

则root树的最大快乐值为:

root_{快乐值}
+{a不来&&a树的最大快乐值}
+{b不来&&b树的最大快乐值}
+{c不来&&c树的最大快乐值}

2、不包括root

则root树的最大快乐值为:

0
+max({a不来&&a树的最大快乐值}, {a来&&a树的最大快乐值})
+max({b不来&&b树的最大快乐值}, {b来&&b树的最大快乐值})
+max({c不来&&c树的最大快乐值}, {c来&&c树的最大快乐值})

递归函数返回值,即子树信息:

class Info {
    int comeMaxHappy;
    int notComeMaxHappy;

    public Info(int comeMaxHappy, int notComeMaxHappy) {
        this.comeMaxHappy = comeMaxHappy;
        this.notComeMaxHappy = notComeMaxHappy;
    }
}

函数:

    public static int maxHappy(Employee root) {
        Info headInfo = process(root);
        return Math.max(headInfo.comeMaxHappy, headInfo.notComeMaxHappy);
    }

    public static Info process(Employee root) {
        if (root.subOrdinates.isEmpty()) return new Info(root.happy, 0);
        int come = root.happy; // root参与,本树最大快乐值
        int notCome = 0; // root缺席,本树最大快乐值
        for (Employee emp : root.subOrdinates) {
            Info subInfo = process(emp);
            come += subInfo.notComeMaxHappy;
            notCome += Math.max(subInfo.comeMaxHappy, subInfo.notComeMaxHappy);
        }
        return new Info(come, notCome);
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值