刷题之完全二叉树的权值和小字辈及根据后序和中序遍历输出先序遍历

news2024/11/24 20:52:23

1、完全二叉树的权值

1)题目

给定一棵包含 N 个节点的完全二叉树,树上每个节点都有一个权值,按从 上到下、从左到右的顺序依次是 A1, A2, ··· AN,如下图所示:

现在小明要把相同深度的节点的权值加在一起,他想知道哪个深度的节点 权值之和最大?如果有多个深度的权值和同为最大,请你输出其中最小的深度。

注:根的深度是 1。

输入格式:

第一行包含一个整数 N(1≤N≤10^5)。

第二行包含 N 个整数 A1, A2, ··· AN (−10^5 <= Ai<=10^5)。

输出格式:

输出一个整数代表答案。

输入样例:

在这里给出一组输入。例如:

7
1 6 5 4 3 2 1

输出样例:

在这里给出相应的输出。例如:

2

 2)题目解析

 题目要求我们输入n个数字,这n个数字是一颗树的层序遍历,并且这是一颗完全二叉树。计算哪一层数字之和最大,并输出该层数。注:根的深度是 1。

 3)代码 

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        int n=sc.nextInt();
        long []arr= new long[n];
        for (int j=0;j<n;j++){
            arr[j]=sc.nextInt();
        }
//第一层只有一个节点,p表示该层的节点数
        int p=1;
//max表示当前 最大权值之和
        long max = 0;
//l表示max所在的层数,l1是跟着循环遍历的层数
        int l=1,l1=1;
//i表示节点总数3,不超过n
        int i=0;
        while (i<n){
            int j=p;
//max1表示当前层的权值之和
            long max1=0;
//j=p,表示该层的节点数
            while (j!=0){
                max1+=arr[i++];
                j--;
                if (i==n)
                    break;
            }
//判断当前层是否是最大权值之和
            if (max<max1) {
                max =  max1;
                l=l1;
            }
//下一层的节点数=p*2,深度=l1+1
            p*=2;
            l1++;
        }
        System.out.println(l);
    }
}

 2、小字辈

1)题目

本题给定一个庞大家族的家谱,要请你给出最小一辈的名单。

输入格式:

输入在第一行给出家族人口总数 N(不超过 100 000 的正整数) —— 简单起见,我们把家族成员从 1 到 N 编号。随后第二行给出 N 个编号,其中第 i 个编号对应第 i 位成员的父/母。家谱中辈分最高的老祖宗对应的父/母编号为 -1。一行中的数字间以空格分隔。

输出格式:

首先输出最小的辈分(老祖宗的辈分为 1,以下逐级递增)。然后在第二行按递增顺序输出辈分最小的成员的编号。编号间以一个空格分隔,行首尾不得有多余空格。

输入样例:

9
2 6 5 5 -1 5 6 4 7


输出样例:

4
1 9

 2)题目解析

 题目要求我们输入N个数,这N个数表示从1到N的其父节点编号,家谱中辈分最高的老祖宗对应的父/母编号为 -1,然后找出其最小辈的编号。输入样例对应图如下图,可以帮助你们更好理解。

 

 3)代码

import java.util.*;

public class Main1 {
    //L表示当前递归到的最大层数
    static int L;
    //使用队列来存储结果,先进先出
    static Queue<Integer> queue=new LinkedList<>();
    //递归函数
    static void sonTree(int []arr,int father,int l){
        for (int i=1;i<arr.length;i++){
            //如果arr[i]=father,表示编号为i的父亲是father,再进入递归函数,
            //寻找以i为父亲的子节点
            if (arr[i]==father){
                sonTree(arr,i,l+1);
            }
        }
        //如果当前递归的l小于L(当前递归到的最大层数),直接return,肯定不是最小辈
        if (l<L)
            return;
        if (l>L){
        //如果当前递归的l大于L(当前递归到的最大层数),即是新的最大递归层数,
        // 清空队列,重新添加元素    
            L=l;
            queue.clear();
        }
        queue.add(father);
    }
    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        int n=sc.nextInt();
        int []arr=new int[n+1];
        int x=0; //x表示-1祖宗的编号
        for (int i=1;i<=n;i++){
            arr[i]=sc.nextInt();
            //记录祖宗的编号
            if (arr[i]==-1)
                x=i;
        }
        //从1楼开始
        int l=1;
        sonTree(arr,x,l);
        System.out.println(L);
        while (queue.size()!=1){
            System.out.print(queue.poll()+" ");
        }
        System.out.print(queue.poll());
    }
}

 上述代码是递归方法,但是因为题目数据量过大,N(不超过 100 000 的正整数),因此部分题给用例会超时或者其他错误,欢迎大佬在评论区给出建议。下面是正确的另一种方法:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;
public class Main {
  public static void main(String[] args) throws IOException {
        //因为题目数据用量特别大,所以用BufferedReader,提高数据读取时间
        BufferedReader bf=new BufferedReader(new InputStreamReader(System.in));
        int n=Integer.parseInt(bf.readLine());
        //因为所给数据是每个人的父母,所以用arr[]来存放第i人的子女
        ArrayList<Integer> arr[]=new ArrayList[n+1];
        for (int i=0;i<n+1;i++){
        //先要给每个arr[]分配内存,不然都是null
            arr[i]=new ArrayList<>();
        }
        int[] count=new int[n+1];//存放每个人的辈分
        Queue<Integer> q=new LinkedList<>();//层序遍历来求辈分
        //如果只有一个人直接输出
        if (n==1){
            System.out.println(1);
            System.out.print(1);
            return;
        }
        //读取n个数据
        String s=bf.readLine();
        String[] ss=s.split(" ");
        int x=0;
        int lzz=0;//记录老祖宗的编号
        for (int i=1;i<=n;i++){
            x= Integer.parseInt(ss[i-1]);
            //记录祖宗的编号
            if (x==-1)
                 lzz=i;
            else//将i加入到该第x个ArrayList集合中,表示第i个人是第x个人的子女,
                arr[x].add(i);
        }
        //先将老祖宗入队
        q.add(lzz);
        int L=1;//表示辈分
        count[lzz]=1;//老祖宗的辈分是1
       while (!q.isEmpty()){
            int t=q.peek();
            q.poll();
            for (int i=0;i<arr[t].size();i++){
                count[arr[t].get(i)]=count[t]+1;//更新每个子女的辈分
                //更新新的最小辈分的值
                L=Math.max(L,count[arr[t].get(i)]);
                //把子女入队
                q.add(arr[t].get(i));
            }
        }
        System.out.println(L);
        boolean b=true;
        //输出
        for (int i=1;i<=n;i++){
            if (count[i]==L){
                if (b){
                    System.out.println(i);
                    b=false;
                }else
                    System.out.println(" "+i);
            }
        }
    }
}

 为了更好理解可以看看下面图,先找到5的子女并放入arr[x]中。子女的辈分值为 二,然后在count[]的相应位置存储其辈分值。然后再找3,4,6的子女并放入3,4,6对应的arr[]中,其对应的子女的辈分值为3·· ···

L为最大的辈分值,即是最小辈分,然后去count[]数组中找与L相等的辈分值,并输出其对应的i值。

 

 3、根据后序和中序遍历输出先序遍历

1)题目

本题要求根据给定的一棵二叉树的后序遍历和中序遍历结果,输出该树的先序遍历结果。

输入格式:

第一行给出正整数N(≤30),是树中结点的个数。随后两行,每行给出N个整数,分别对应后序遍历和中序遍历结果,数字间以空格分隔。题目保证输入正确对应一棵二叉树。

输出格式:

在一行中输出Preorder: 以及该树的先序遍历结果。数字间有1个空格,行末不得有多余空格。

输入样例:

7
2 3 1 5 7 6 4
1 2 3 4 5 6 7

输出样例:

Preorder: 4 1 3 2 6 5 7

 2)题目解析

题目给定我们N个数,然后在下两行分别给出由这N个数组成的一颗二叉树的后序遍历和中序遍历。然后要求我们输出前序遍历。我们应该先根据后序遍历和中序遍历,构建出这颗二叉树,然后再进行前序遍历并输出。

 3)代码

import java.util.*;

public class Main {
    public static class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;
    TreeNode(int val) {
        this.val = val;
    }
}
    public static void main(String[] args) {
    Scanner sc=new Scanner(System.in);
    int n=sc.nextInt();
    int []hx=new int[n];
    int []qx=new int[n];
    for (int i=0;i<n;i++){
        hx[i]=sc.nextInt();
    }
    for (int i=0;i<n;i++){
        qx[i]=sc.nextInt();
    }
    TreeNode tree=buildTree(qx,hx);

    //使用List集合存储该树的前序遍历,方便输出
    List<Integer> list=new ArrayList<>();
    preorder(tree,list);
    int j=0;
    System.out.print("Preorder: ");
    while (j!=list.size()-1){
        System.out.print(list.get(j)+" ");
        j++;
    }
        System.out.print(list.get(j));
}
     //前序遍历,使用List 集合存储
     public static void preorder(TreeNode root, List<Integer>list){
         if (root == null) {
             return;
         }
         list.add(root.val);
         preorder(root.left, list);
         preorder(root.right, list);
     }
    //前序遍历
     public static void preOrder(TreeNode head) {
         if (head == null) {
             return;
         }
         System.out.print(head.val + " ");
         preOrder(head.left);
         preOrder(head.right);
     }

    static int index = 0;
    //构建二叉树
    public static TreeNode buildTree(int[] inorder, int[] postorder) {
        index = postorder.length-1;
        return buildTree(postorder, inorder, 0, inorder.length);
    }
    // index不断在后序遍历中找根节点,每次找完之后,根据找到的根节点将中序遍历分成
    //左右两部分,左侧为根的左子树,右侧为根的右子树
    // 注意:与前序中序还原二叉树不同的是,此次需要先还原右子树
    private static TreeNode buildTree(int[] postorder, int[] inorder, int left,
 int right){
        //如果left>=right,即左右节点遍历到同一节点,这时就要停止递归
        if(left >= right){
            return null;
        }
        // 创建根节点
        TreeNode root = new TreeNode(postorder[index]);
        // 在中序遍历结果中找到根的位置
        int rootIdx = left;
        //寻找根位置
        while(rootIdx < right){
            if(inorder[rootIdx] == postorder[index])
                break;
            rootIdx++;
        }
        index--;
        //要先构建右子树,再构建左子树,这是由后序遍历决定的
        //[rootIdx+1, right): 右子树中的所有节点的范围
        // 递归创建根的右子树
        root.right = buildTree(postorder, inorder, rootIdx+1, right);
        //[left, rootIdx):左子树中的所有节点的范围
        // 递归创建根的左子树
        root.left = buildTree(postorder, inorder, left, rootIdx);
        return root;
    }
}

其实根据后序和中序写出前序 和根据前序和中序写出后序是差不多的,只不过是从前往后遍后序,先构建左子树,过程都是差不多的。希望可以用帮助到大家。

 👍👍👍看到这里了还不点个赞👍👍👍

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/47233.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

开关电源32个检测项目、检测方法与检测设备(下)

开关电源是电器必备&#xff0c;本文详细介绍了开关电源的32个常见检测项目、检测方法与仪器&#xff0c;内容较多&#xff0c;前些日子介绍了上部分16个项目&#xff08;点击阅读&#xff09;&#xff0c;今天介绍剩下的16个项目。抱歉久等了&#xff01; 过压保护测试 一、目…

MySQL数据库事务控制

目录 一、事务控制概念 二、事务控制特性 三、事务控制相关命令 1、测试begin和commit&#xff08;开始事务和提交事务&#xff09; 2、测试事务回滚rollback 四、总结 1、事务的ACID特性 2、事务之间的相互影响 3、事务的隔离级别 一、事务控制概念 在MySQL中用于处理…

上海大治河二线船闸总体设计与结构计算

目录 第一章 设计基本资料 1 1.1工程概况 1 1.2 货运量预测 1 1.3 建筑物设计等级 1 1.4 通航情况及计算参数的选取 1 1.5 设计船型 2 1.6 特征水位表 2 1.7 水文气象资料 3 1.8 工程地质 3 第二章 总体设计 4 2.1 船闸地理位置确定 4 2.2 船闸线、级数确定 5 2.3 船闸的基本尺…

【能效管理】变电所运维云平台在上海某医院的设计分析

摘要&#xff1a;本文概述了变电所电力运维技术&#xff0c;分析了医院变电所中存在的技术设备老化和技术荷载不足的技术性问题&#xff0c;并从主变低压进出线路监测故障、环境监测故障、设备档案记录、运维排班记录、分析报告五个方面探讨了变电所电力运维技术的具体应用。变…

1. 语音类实现 (实现读取wav/pcm,STFT)

[C 基于Eigen库实现CRN前向推理] 第一部分&#xff1a;WavFile.class (实现读取wav/pcm,实现STFT) 前言&#xff1a;(Eigen库使用记录)第一部分&#xff1a;WavFile.class (实现读取wav/pcm,实现STFT)第二部分&#xff1a;Conv2d实现第三部分&#xff1a;TransposedConv2d实现…

荧光标记肽(Arg)9, FAM-labeled

(Arg)9, FAM-labeled 是一种带有 FAM 标记的 ARG&#xff0c;属于细胞穿透肽 (CPP)。CPPs 已成为一种强大的工具&#xff0c;用于将生物活性物质输送到完整细胞胞质中。(Arg)9, FAM-labeled, a cell-penetrating peptide (CPP), is a nona-arginine (ARG) with FAM label. CPPs…

mac上的python2安装

iiPython Release Python 2.7.18rc1 | Python.orgThe official home of the Python Programming Languagehttps://www.python.org/downloads/release/python-2718rc1/不小心把mac上的python2给删除了&#xff0c;发现老的nodejs项目需要pytho2&#xff0c;这下晕了&#xff0c;…

秸秆制粒机的总体设计

目 录 摘 要 I Abstract II 第一章 绪论 1 1.1选题背景及意义 1 1.2国内外生物质制粒机的发展现状 4 1.2.1国外发展现状 4 1.2.2国内发展现状 5 1.3目前主要的制粒机类型及其制粒方法 9 1.3.1活塞式制粒机 9 1.3.2螺旋式制粒机 10 1.3.3模压颗粒制粒机 10 1.4秸秆燃料制粒加工技…

MES工单工艺线路条码系统NetMVC源码 MES条码管理系统源码

系统详情功能&#xff1a; 生产管理、基础数据维护、设备统计、新增设备统计、水质地图、故障统计、设备分布、耗材统计 生产管理&#xff1a;工单管理、工单检测、工单查询、工单生产、工位扫描、工位设置、滤芯包装、 包装打印、包装管理、条码管理、生产进度图 基础数据维…

性能测试之cpu 分析

cpu 架构 --中央处理器 运算器&#xff1a; 真正进行计算的单元控制器&#xff1a; leader寄存器&#xff1a; 存储 指令、数据、地址时钟 控制程序运行时长 内存 程序代码、网络数据&#xff0c;外部数据进入cpu的桥梁&#xff0c;内存的速度&#xff0c;要比cpu的速度 cp…

基于PHP+MySQL企业网络推广平台系统的设计与实现

企业网络推广平台系统具有很强的信息指导性特征,采用PHP开发企业网络推广平台系统 给web带来了全新的动态效果,具有更加灵活和方便的交互性。在Internet中实现数据检索越来越容易,可以及时、全面地收集、存储大量的企业资源信息以及进行发布、浏览、搜索相关的信息。让企业、个…

当世界杯撞上电商销售旺季,独立站卖家如何爆单不爆冷?

今年的世界杯频频爆冷&#xff0c;就像如今的天气一样&#xff0c;令人瑟瑟发抖。由于卡塔尔当地的特殊气候&#xff0c;2022年世界杯选择在冬季举行&#xff0c;于是就有了电商销售旺季遇上世界杯。两股热度叠加&#xff0c;造就了空前的销售时机。 感恩节、黑五、网一&#x…

CSDN【top1】Pytest接口测试框架实战项目搭建

一、前言 想想之前玩的框架&#xff0c;做的项目都是把数据用例冗余到一起的&#xff0c;不符合数据用例分离的思想&#xff0c;所以准备基于pytest搭建个测试框架&#xff0c;支持数据用例分离&#xff0c;接下来会用一系列文章逐步介绍整个框架是怎么搭建起来的。 二、项目结…

[附源码]计算机毕业设计springboot高校体育场馆管理系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

TMA三均线股票期货高频交易策略的R语言实现

趋势交易策略是至今应用最广泛以及最重要的投资策略之一&#xff0c;它的研究手段种类繁多&#xff0c;所运用的分析工具也纷繁复杂&#xff0c;其特长在于捕捉市场运动的大方向。股指期货市场瞬息万变&#xff0c;结合趋势分析方法&#xff0c;量化投资策略能够得到更有效的应…

项目使用smart-doc+Torna自动化创建api文档

首先部署Torna&#xff0c;我这里是用docker部署的 准备工作&#xff1a;1 docker 环境 2 torna 所需的sql脚本&#xff08;可以去github 找最新的&#xff09; DROP TABLE IF EXISTS compose_additional_page; CREATE TABLE IF NOT EXISTS compose_additional_page (id bigi…

jupyter使用教程及python语法基础

前言 上回说到搭建jupyter环境&#xff0c;今天的文章主要就是熟悉jupyter上的基本操作&#xff0c;以及python的一些基础语法。 正文 1、熟悉jupyter界面使用方法 通过命令行进入jupyter后&#xff0c;选择python3。 进去之后就是如下界面&#xff0c;要熟悉以下操作。当…

SAP ABAP——数据类型(二)【TYPES自定义数据类型详解】

&#x1f4ac;个人网站&#xff1a;【芒果个人日志】​​​​​​ &#x1f4ac;原文地址&#xff1a;SAP ABAP——数据类型&#xff08;二&#xff09;【TYPES自定义数据类型详解】 - 芒果个人日志 (wyz-math.cn) &#x1f482;作者简介&#xff1a; THUNDER王&#xff0c;一名…

python学习笔记(11)---(模块与包)

第九章 模块与包 1.模块&#xff08;modules&#xff09; &#xff08;1&#xff09;概念&#xff1a;将实现某一特定功能的代码放置在一个文件中&#xff0c;以便于其他程序进行导入使用&#xff0c;可以避免函数名、变量名的冲突&#xff0c;该文件称为模块&#xff0c;拓展…

RtspServer之LibRtsp解决闪退 新增鉴权(用户名密码登录)

编程语言&#xff1a;C 目标平台&#xff1a;arm&#xff08;hi3519&#xff09;注&#xff1a;因为代码是纯C语言按道理可以移植到各种平台 基础库&#xff1a;librtsp&#xff08;存在功能补全&#xff0c;有一定的bug&#xff09; 因为项目需求需要在海思平台实现IPC…