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

 

 

 思路(自己):除了根节点无父节点外,去除其余节点必定会与父节点分离。每次切割之后都要考虑消除了几个分支。若消除的是k节点,查询数组,(for i=0;i<a.length;i++)a[i]==k的情况必有0~2个。

(需注意:以下情况为k不为0,即k不是根节点的情况下,是根节点则比较特殊,在实现过程中出过错!!!)

  • 若为0个,则该节点为叶子节点,分数为a.length-1;
  • 若为1个,则切割完之后有两部分。(怎么确定两部分的数目呢?)
  • 若为2个,则切割完之后有三部分。

确定以节点K为根节点的子树所含元素大小,通过一个函数实现:int treeSum;使用迭代的思想。

//定义treeSum函数,返回以指定节点为根节点的子树元素个数
    int treeSum(int num, ArrayList<Integer> list){
        int n=1;
        //如果该节点没有子节点,说明是叶子节点,返回1
        if(!list.contains(num))
            return n;
        //该节点只有一个子节点,返回子节点数目+1
        if(list.indexOf(num)==list.lastIndexOf(num))
            return treeSum(list.indexOf(num),list)+1;
        return treeSum(list.indexOf(num),list)+treeSum(list.lastIndexOf(num),list)+1;
    }

然后通过for循坏,把每次的得分情况存入list1中,最后进行排序,去最后一个元素,记录最后一个元素的个数,即为解。实现过程如下:

import java.util.ArrayList;
import java.util.List;
import java.util.Collections;
class Solution {
 public int countHighestScoreNodes(int[] parents) {
        //将数组元素导入list中方便操作
        ArrayList<Integer> list= new ArrayList<>(parents.length);
        for(Integer i:parents){
            list.add(i);
        }
        //定义list1存储去除每个元素后的得分
        List<Integer> list1=new ArrayList<>(parents.length);
        //根节点需要特殊对待
        if(!list.contains(0)){
            list1.add(0);
        }else if(list.indexOf(0)==list.lastIndexOf(0)){
            list1.add(parents.length-1);
        }else {
            int son=list.indexOf(0);
            int j=treeSum(son,list);
         //   int k=treeSum(0,list)-j-1;
            list1.add(j*(parents.length-j-1));
            
        }
        for (int i = 1; i < parents.length; i++) {
            //如果节点不含子节点,则其为叶子节点,分数为总长度减一
            if(!list.contains(i)){
                list1.add(parents.length-1);
                continue;
            }
            //如果只有一个子树,则分割后为两部分
            if(list.indexOf(i)==list.lastIndexOf(i)){
                int j=treeSum(i,list);
                list1.add((j-1)*(parents.length-j));
                continue;
            }
            //含有两个子树,分割后为三部分
            if(list.indexOf(i)!=list.lastIndexOf(i)){
                int son=list.indexOf(i);
                int j=treeSum(son,list);
                int k=treeSum(i,list)-j-1;
                list1.add(j*k*(parents.length-1-j-k));
                continue;
            }
        }
        Collections.sort(list1);
        int max=list1.get(list1.size()-1);
        int res=0;
        for(Integer i:list1){
            if(i==max) res++;
        }
        return res;
    }
    //定义treeSum函数,返回以指定节点为根节点的子树元素个数
    int treeSum(int num, ArrayList<Integer> list){
        int n=1;
        //如果该节点没有子节点,说明是叶子节点,返回1
        if(!list.contains(num))
            return n;
        //该节点只有一个子节点,返回子节点数目+1
        if(list.indexOf(num)==list.lastIndexOf(num))
            return treeSum(list.indexOf(num),list)+1;
        return treeSum(list.indexOf(num),list)+treeSum(list.lastIndexOf(num),list)+1;
    }
}

这个题我做了接近两个小时,算是比较悲伤的了,┭┮﹏┭┮ 最后让人绝望的是又超出时间限制了!

 好了,看完官方答案,看不懂,看了另一位大牛的,勉强理解了

class Solution {
    //使用两个数组保存二叉树的左右节点,索引为父节点
    int[] left, right;
    //最大分数, 注意溢出,这里用 long
    long maxScore;
    //最大分数量
    int cnt;
    //整棵树大小
    int n;

    public int countHighestScoreNodes(int[] parents) {
        n = parents.length;
        left = new int[n];
        right = new int[n];
        //初始化树的表示,-1表示空节点
        Arrays.fill(left, -1);
        Arrays.fill(right, -1);
        //构建树的表示
        for (int i = 1; i < n; i++) {
            //填充左右节点无所谓,这里优先填左节点
            if (left[parents[i]] == -1) {
                left[parents[i]] = i;
            } else {
                right[parents[i]] = i;
            }
        }
        //dfs处理更新相关值
        dfs(0);
        return cnt;
    }

    //返回以此节点为根节点的子树的大小
    private long dfs(int node) {
        if (node == -1) {
            return 0;
        }
        //dfs 获取左右子树大小
        long leftSize = dfs(left[node]), rightSize = dfs(right[node]);
        //计算三个联通块的乘积
        long score = Math.max(leftSize, 1) * Math.max(rightSize, 1) * Math.max(n - leftSize - rightSize - 1, 1);
        if (score == maxScore) {
            cnt++;
        } else if (score > maxScore) {
            maxScore = score;
            cnt = 1;
        }
        return leftSize + rightSize + 1;
    }
}

实力还有待提高!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值