[PAT甲级]1004. “家族树的每一层有多少个叶子节点“

题目描述

 大致意思就是:

       给你一棵树(不是二叉树,就是普通的树),输入数据会告诉你有多少个非叶子节点,以及这些非叶子节点各自的子节点列表,让你构建出这个树,最终从上到下依次输出每一层的叶子节点个数。

我的思路:

利用深度优先的想法来处理。

先用一种数据结构把非叶子节点和它的子节点列表存在一起,比如C++的vector容器,JAVA的Map集合,都可以实现类似的效果。这样能有效的帮助我们构造出这棵树的整体样貌。

然后说一下怎么处理。

  · 我们需要一个数组来记录每一层的叶子节点数,题目也说了,总节点数0<N<100,那么这棵树最多是100层的,所以我们定义一个leaf[100],leaf[i] 就是i层的叶子节点数。

  · 在每一次递归中,我们要知道自己当前是哪个节点,在哪一层,所以dfs可以定义成:

void dfs(int cur , int level)

       然后,学过数据结构的同学肯定不难想到,逐层向下递归的过程中,到了叶子节点那肯定就不能再往下了,所以说判断当前节点是不是叶子节点,就是我们的退出条件。然后,除了退出,我们还要把当前层对应的叶子节点数+1,即 leaf[level] ++

       如果当前节点不是叶子节点,那我们就从vector容器中拿出当前节点的子节点列表,然后挨个传进去调用dfs进行递归。等到dfs执行结束,我们的leaf数组也就更新完毕了,接下来从0层开始一直到最大深度,逐层输出leaf [ i ]即可。

代码实现

我一开始因为对C++了解的不够多,不认识vector这种东西,出于懒得写链表,就用JAVA写了一个版本(List很好用捏),后来对vector有了部分了解后,用C++重写了一版。

JAVA实现:

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;

public class Problem1004 {
	// 因为Max(N) = 100 , 所以最大层数就是100 ,开个100大小的数组来记录每层的叶子节点数
	private static int[] nums = new int[100];
	private static int maxLevel = 0;
    // 用Map来存放非叶子节点以及它的子节点列表
	private static Map<Integer, List<Integer>> all = new HashMap<>();
	
	
	public static void dfs(int cur,int level) {
	if(level>maxLevel) {
		// 更新最大层数
		maxLevel = level;
	}
	
	// map里没存当前节点,说明当前节点就是个叶子节点,对应层叶子数+1并退出
	if(!all.containsKey(cur)) {
		//没有子节点,当前节点是个叶子节点,对应层数的叶子节点数+1
		nums[level]++;
		return;
	}
	
	// 接下来,若不是叶子节点则继续向下走
	for(Integer son:all.get(cur)) {
		    dfs(son, level+1);
	    }
    }
	
	
	public static void main(String[] args) {
		Scanner scanner = new Scanner(System.in);
		int N,M;
		N = scanner.nextInt();
		M = scanner.nextInt();
		
		for(int i=0;i<M;i++) {
			// 先输入这个非叶子节点的信息,作为根节点
			Integer rootOrder = scanner.nextInt();
			// 用来暂时存储这非叶子节点的所有子节点
			List<Integer> tempList = new ArrayList<>();
			// 这一层的节点数
			int k = scanner.nextInt();
			for(int j=0;j<k;j++) {
				// 把儿子节点存入临时集合
				Integer order = scanner.nextInt();
				tempList.add(order);
			}
			// 将根节点存入总记录表中
			all.put(rootOrder, tempList);
		}
		dfs(1,0);
		System.out.print(nums[0]);
		for(int i=1;i<=maxLevel;i++) {
			System.out.print(" " + nums[i]);
		}
		System.out.println();
	}
}

C++实现:

#include<iostream>
#include<vector>
using namespace std;


/*
    已AC 2022/11/28 晚
    JAVA交了一版,AC了,这次试着用c++来重新写一下
*/

// 第一次尝试vector,这里用来对应每个根节点的子节点列表(即sons[i] 就是i节点的子节点列表)
vector<int> sons[100];
// leaf数组用来记录每一层的叶子节点的个数
int leaf[100];
int maxLevel = 0;

void dfs(int cur,int level){
    // 若当前深度(层数)已经大于之前记录的最大深度,那么就更新最大层数的值
    if(level>maxLevel){
        maxLevel = level;
    }
    if(sons[cur].size()==0){
        // 说明当前节点没有子节点,是个叶子节点,那么这一层的叶子节点数应该+1
        leaf[level]++;
        // 因为没有子节点,所以退出递归
        return;
    }

    //接下来处理有子节点的
    for(int i=0;i<sons[cur].size();i++){
        dfs(sons[cur][i],level+1);
    }

}

int main(){
    int N,M,temp,ID,K;
    cin>>N>>M;
    for(int i=0;i<M;i++){
        cin>>ID>>K;
        for(int j=0;j<K;j++){
            cin>>temp;
            // 将子节点的序号加入到根节点的子节点列表中去
            sons[ID].push_back(temp);
        }
    }

    // 题目规定01是第一个根节点,我们用int接收,所以这里传1,同时它是第0层的
    dfs(1,0);
    // 递归计算处理后,leaf数组已经被更新,我们只需要从0到最大层数进行输出即可(因为再往后面的层压根也没有节点)

    //啊对,这里因为他要求最后一个结果后面不能有空格,所以我们先输出一个  然后按照 空格 值的格式输出
    cout<<leaf[0];
    for(int j=1;j<=maxLevel;j++){
        cout<<" "<<leaf[j];
    }
    cout<<endl;

    return 0;
}

二者效率比较:

                                                                  (JAVA实现) 

可能是我List、Map占的空间比较多了,不过还是过了,没有超出限制。

                                                                      (C++实现)

思路差不多,C++的效果会好一些,也有可能我JAVA写太烂- -

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值