2021.10.25 力扣-统计最高分的节点数目

该博客介绍了如何解决一个算法问题,即在给定一棵二叉树和每个节点的父节点信息的情况下,计算具有最高得分的节点数量。最高得分是通过删除节点及其关联边后,剩余子树大小的乘积。博主提出了一种方法,首先构建完整的二叉树,然后遍历计算每个节点的左、右子树大小,最后根据节点的子树大小计算分数并找出最高得分的节点数。
摘要由CSDN通过智能技术生成

题目描述:

给你一棵根节点为 0 的 二叉树 ,它总共有 n 个节点,节点编号为 0 到 n - 1 。同时给你一个下标从 0 开始的整数数组 parents 表示这棵树,其中 parents[i] 是节点 i 的父节点。由于节点 0 是根,所以 parents[0] == -1 。

一个子树的 大小 为这个子树内节点的数目。每个节点都有一个与之关联的 分数 。求出某个节点分数的方法是,将这个节点和与它相连的边全部 删除 ,剩余部分是若干个 非空 子树,这个节点的 分数 为所有这些子树 大小的乘积 。

请你返回有 最高得分 节点的 数目 。

方法一:

class node
{
public:
    node* left;
    node* right;
    int leftcount;      //左子树中所含的节点数
    int rightcount;     //右子树中所含的节点数
    node()
    {
        left = nullptr;
        right = nullptr;
        leftcount = 0;
        rightcount = 0;
    }
};
class Solution {
public:
    

    int count(node* cur)    //计算各个节点的左右子树各自的节点个数
    {
        if (cur == nullptr) return 0;
        cur->leftcount = count(cur->left);
        cur->rightcount = count(cur->right);
        return cur->leftcount + cur->rightcount + 1;
    }

    int countHighestScoreNodes(vector<int>& parents) {
        int n = parents.size();
        vector<node*> nodes(n);
        //对各个节点初始化
        for (int i = 0; i < n; i++)
        {
            nodes[i] = new node();
        }
        node* root = new node();    //根节点
        for (int i = 0; i < n; i++)
        {
            //当前遍历到的节点是i,它的父节点是par
            int par = parents[i];
            if (par == -1)
            {
                root = nodes[i];
            }
            else
            {
                if (nodes[par]->left == nullptr)
                {
                    nodes[par]->left = nodes[i];
                }
                else
                {
                    nodes[par]->right = nodes[i];
                }
            }
        }
        count(root);
        //开始寻找最高得分的节点的数目
        int ans = 0;            //最高得分的节点的数目
        long long maxscore = LONG_MIN; //最高得分
        for (int i = 0; i < n; i++)
        {
            long long curscore = 0;
            //由于要进行乘法运算,所以如果a、b、c为0的话,就把他们设为1
            long long a = nodes[i]->leftcount == 0 ? 1 : nodes[i]->leftcount;         //左子树的节点个数
            long long b = nodes[i]->rightcount == 0 ? 1 : nodes[i]->rightcount;       //右子树的节点个数
            long long c = n - nodes[i]->leftcount - nodes[i]->rightcount - 1; //nodes[i]去掉与其父节点连接的边后,其父节点一方的节点个数
            c = c == 0 ? 1 : c; //如果nodes[i]是根节点的情况,那么就让c为1

            curscore = a * b * c;
            //cout << a << " " << b << " " << c << endl;;

            if (curscore > maxscore)
            {
                maxscore = curscore;
                ans = 1;
            }
            else if (curscore == maxscore)
            {
                ans++;
            }
        }
        return ans;
    }
};

昨天周赛的第三题。

我的想法是通过parents构造一棵完整的二叉树,然后再遍历一遍,计算各个节点的左子树的结点个数和右子树的节点个数。

最后计算分数时,分为三个部分:与左节点连接的边、与右右节点连接的边和与父节点连接的边。

例如上图中的节点2,他的左子树的结点个数为1;右子树的结点个数为1;去掉与父节点所连接的边后,就相当于将以节点2为根节点的子树从这整棵树中去掉,所以用整棵树的节点个数n减去这棵子树,为 n - 3 = 2。最后将三部分相乘即为答案。

注意由于分数的计算方式是乘法,所以若a、b、c中有一个的值为0,就将其设为1,防止导致乘法结果为0。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值