【蓝桥杯】历届真题 左hai子右兄弟(省赛)Java

资源限制

内存限制:256.0MB   C/C++时间限制:1.0s   Java时间限制:3.0s   Python时间限制:5.0s

问题描述

        对于一棵多叉树,我们可以通过 “左孩子右兄弟” 表示法,将其转化成一棵二叉树。

        如果我们认为每个结点的子结点是无序的,那么得到的二叉树可能不唯一。换句话说,每个结点可以选任意子结点作为左孩子,并按任意顺序连接右兄弟。

        给定一棵包含 N​​ 个结点的多叉树,结点从 1​​ 至 N​ 编号,其中 1 号结点是根,每个结点的父结点的编号比自己的编号小。请你计算其通过 “左孩子右兄弟” 表示法转化成的二叉树,高度最高是多少。

注:只有根结点这一个结点的树高度为 0​

        例如如下的多叉树:

  

输入格式
        输入的第一行包含一个整数 N​​​。

        以下 N−1​​ 行,每行包含一个整数,依次表示 2​ 至 N 号结点的父结点编号。

输出格式
        输出一个整数表示答案。

样例输入
5
1
1
1
2
样例输出
4

评测用例规模与约定
        对于 30%​​ 的评测用例,1≤N≤20​;
        对于所有评测用例,1≤N≤100000。

【基础知识要求】

        首先要知道何为“左孩子右兄弟”表示法,不然这个题是要直接pass的。

        何为“左孩子右兄弟”表示法?

        答:大家都知道,在树结构中,同一层的节点互为兄弟节点。上层与下层相连的节点为父子节点。那么,所谓的“孩子兄弟表示法”,指的是用将整棵树用二叉链表存储起来,从树的根节点开始,依次存储各个结点的孩子结点和兄弟结点。

        因此,各个节点又包含了三部分内容:

        1.节点的值;

        2.指向孩子结点的指针;

        3.指向兄弟结点的指针;

        

         而通过孩子兄弟表示法,任意一棵普通树都可以相应转化为一棵二叉树,它们之间是一一对应的。因此,孩子兄弟表示法可以作为将普通树转化为二叉树的最有效方法,通常又被称为"二叉树表示法"或"二叉链表表示法"。

思路与分析

       从根节点向下看,当前节点的最深深度 = 当前节点的子节点(一个在左,其他的节点都在右侧。因为左孩子右兄弟的原则) + 所有子节点距离当前子节点的最深深度。也就是说,树的最大高度=父节点孩子的数目+以它的孩子为父节点的子树的最大高度。

        同样,题内有一个细节需要我们注意:根结点这一个结点的树高度为 0​

代码

import java.util.*;

public class Main {
    //声明一个数据类型,模拟二叉树
    public static Map<Integer,ArrayList<Integer>> erTree = new HashMap<>();
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        //使用Integer这一包装类而不使用int的原因为:Integer是对象,int仅表示值
        Integer n = sc.nextInt();

        for(int i = 2; i <= n; i++) {
            Integer fa = sc.nextInt();
			//判断是否存在该父节点,没有则添加
            if(!erTree.containsKey(fa)) {
                ArrayList<Integer> list = new ArrayList<>();
                erTree.put(fa,list);
            }
            erTree.get(fa).add(i);
        }
        System.out.println(shen(1));
    }
    public static int shen(int n) {
        //通过判断舍弃无效数据,优化运算量
        if(!erTree.containsKey(n)) {
            return 0;
        }
        //获得子树
        ArrayList<Integer> list = erTree.get(n);
        //获得以1为父节点的孩子节点的数目
        int size = list.size();
        int max = 0;
        //遍历子树,获得以n为父节点的子树的最大高度
        for(Integer i : list) {
            max = Math.max(max,shen(i));
        }
        return size + max;
    }
}

        

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值