LeetCode 2049. 统计最高分的节点数目题解

2049. 统计最高分的节点数目题解

题目来源:2049. 统计最高分的节点数目

2022.03.11 每日一题

LeetCode 题解持续更新中Github仓库地址 CSDN博客地址

今天的题目眨眼一看可能有点懵逼没太看明白,第一反应是相乘的最大值,那不就是把0扔出去就行了,思路这么简单的话,middle不太可能,一仔细看,发现与节点对应的 value 值无关,是除了删除节点以外构成树的大小的乘积

那让我们来理性分析一下(以通用情况分析,并非单单只有 二叉树)

一棵树,删除了一个节点以后他还剩什么

让我们来讨论一下,

  • 如果删除的点是根节点,那么剩下的东西就是根节点的各个子节点形成的新的树,那么其结果就应该是 s u m = f ( u 1 ) + f ( u 2 ) + f ( u 3 ) + … … + f ( u k ) sum=f(u_1)+f(u_2)+f(u_3)+……+f(u_k) sum=f(u1)+f(u2)+f(u3)++f(uk)
  • 如果删除的是非根节点,那么最后剩余的东西就是,以删除节点为根节点的各个子节点形成的新的树 + 删除节点其祖先节点其余的树 s u m = f ( u 1 ) + f ( u 2 ) + … … + f ( u k ) + f ( r l ) sum=f(u_1)+f(u_2)+……+f(u_k)+f(r_l) sum=f(u1)+f(u2)++f(uk)+f(rl)

一共就这两种情况汇总一下就是 拿到一个节点,最后会剩下一个左子树(如果存在的话)、一个右子树(如果存在的话)、以及一个其祖先节点剩余的部分(如果删除节点不是根节点的话)

现在问题就拆分的很简单了,分别计算三种树的数量最后相乘,左右两个子树计算起来还容易,那么剩下的那个怎么办呢,我们可以使用树的总体大小减去左右子树的大小后 再 减一(减一是减去删除的节点)

class Solution {
public:
    // 创建一个 哈希表,key 表示父节点,val 表示子节点集合
    unordered_map<int, vector<int>> cnt;
    vector<int> f;

    int countHighestScoreNodes(vector<int> &parents) {
        int len = parents.size();
        for (int i = 1; i < len; i++)
            cnt[parents[i]].push_back(i);
        // 定义数组 f 来存储各个节点的值
        f = vector(len, 0);
        dfs(0);

        // 统计得分最高的树的个数
        int res = 0;
        // 统计当前得分最高的分数
        long long ans = 0;

        // 遍历数组 f ,判断
        for (int i = 0; i < len; i++) {
            // 统计当前情况下的乘积
            long temp = 1;
            // 遍历 i 的子节点,统计各个树的大小
            for (int num: cnt[i])
                temp *= f[num];
            // 判断当前节点是否是根节点
            if (i != 0)
                temp *= len - f[i];
            // 判断 是否是当前结果最大值
            // 如果不是,更新最大值,并且重置 结果 res
            if (temp > ans) {
                ans = temp;
                res = 1;
            } else if (ans == temp) {
                // 如果与最大值相同,结果加一
                res++;
            }
        }
        return res;
    }

    // 定义递归函数
    int dfs(int start) {
        // 定义变量统计相应节点的个数
        int sum = 1;
        // 遍历 节点 start 旗下的子节点,继续向下递归
        for (int num: cnt[start]) {
            sum += dfs(num);
        }
        // 将 sum 值进行统计,执行记忆化搜索
        f[start] = sum;
        // 返回 sum 值供上一层进行使用
        return sum;
    }
};
class Solution {
    // 创建一个 哈希表,key 表示父节点,val 表示子节点集合
    Map<Integer, ArrayList<Integer>> cnt = new HashMap();
    int[] f;

    public int countHighestScoreNodes(int[] parents) {
        int len = parents.length;
        for (int i = 1; i < len; i++) {
            ArrayList<Integer> arr = cnt.getOrDefault(parents[i], new ArrayList<>());
            arr.add(i);
            cnt.put(parents[i], arr);
        }

        // 定义数组 f 来存储各个节点的值
        f = new int[len];
        dfs(0);

        // 统计得分最高的树的个数
        int res = 0;
        // 统计当前得分最高的分数
        long ans = 0;

        // 遍历数组 f ,判断
        for (int i = 0; i < len; i++) {
            // 统计当前情况下的乘积
            long temp = 1;
            // 遍历 i 的子节点,统计各个树的大小
            for (int num : cnt.getOrDefault(i, new ArrayList<>()))
                temp *= f[num];
            // 判断当前节点是否是根节点
            if (i != 0) temp *= len - f[i];
            // 判断 是否是当前结果最大值
            // 如果不是,更新最大值,并且重置 结果 res
            if (temp > ans) {
                ans = temp;
                res = 1;
            } else if (ans == temp) {
                // 如果与最大值相同,结果加一
                res++;
            }
        }
        return res;
    }

    // 定义递归函数
    int dfs(int start) {
        // 定义变量统计相应节点的个数
        int sum = 1;
        // 遍历 节点 start 旗下的子节点,继续向下递归
        for (int num : cnt.getOrDefault(start, new ArrayList<>())) {
            sum += dfs(num);
        }
        // 将 sum 值进行统计,执行记忆化搜索
        f[start] = sum;
        // 返回 sum 值供上一层进行使用
        return sum;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值