PAT (Advanced Level) Practice 1004 Counting Leaves—Python(dfs深度搜索)

摘要

本题主要考察做题人对树这种数据结构的dfs(深度搜索)的应用,总体来说不算一道特别难的算法题。

原题

A family hierarchy is usually presented by a pedigree tree. Your job is to count those family members who have no child.

Input Specification:

Each input file contains one test case. Each case starts with a line containing 0<N<100, the number of nodes in a tree, and M (<N), the number of non-leaf nodes. Then M lines follow, each in the format:

ID K ID[1] ID[2] ... ID[K]

where ID is a two-digit number representing a given non-leaf node, K is the number of its children, followed by a sequence of two-digit ID's of its children. For the sake of simplicity, let us fix the root ID to be 01.

The input ends with N being 0. That case must NOT be processed.

Output Specification:

For each test case, you are supposed to count those family members who have no child for every seniority level starting from the root. The numbers must be printed in a line, separated by a space, and there must be no extra space at the end of each line.

The sample case represents a tree with only 2 nodes, where 01 is the root and 02 is its only child. Hence on the root 01 level, there is 0 leaf node; and on the next level, there is 1 leaf node. Then we should output 0 1 in a line.

Sample Input:

2 1
01 1 02

Sample Output:

0 1

题目意思

        现在有一棵树,树上有N个结点,其中有M个父结点,接下来M行每行第一个是父结点名称,第二个是该父节点有多少个子节点,第三个以后是其每个子结点的名称。现在要找到树的每一层有多少个叶子结点(没有子结点的结点称为叶子结点)并输出。

思路

        本题首先要做的就是把题目给的数据用树保存下来,考虑到测试用例的数据会存在所给父结点乱序的情况,使用字典以"node_id:[*children]"的方式保存父结点和子结点会自动对父结点进行排序。

        然后对树进行dfs深搜,每次搜索一层时如果发现某个结点在tree的键值里表示该结点是父节点,此时需要判断该结点是否被搜索过,否则可能会进入无限递归,然后对为搜索的继续递归即可。若不在tree的键值里,则将该深度的叶子结点计数+1后return即可。

测试样例

输入

8 4
01 2 02 03
02 2 04 05
04 2 07 08
03 1 06

输出

0 0 2 2

Python代码

def dfs(node, depth):
    visited[node] = True  # 每次搜一个结点就讲节点改成已经遍历
    global max_depth
    max_depth = max(max_depth, depth)  # 更新最大深度
    if node not in tree:  # 判断当前结点是否在tree里,不在就表示是叶子结点
        leave_num[depth] += 1
        return
    for child in tree[node]:  # 如果是父结点就搜索该结点的所有子节点
        if child not in visited:  # 必须判断是否被搜索过,否则会导致无限递归
            dfs(child, depth + 1)


# n为节点数,m为父节点数
n, m = map(int, input().split())
# 用字典存储树能自动对结点排序避免输入乱序,在tree中只保留所有有子结点的结点
tree = {}
for i in range(m):
    node_id, child_num, *children = input().split()  # 输入所有的父节点,子节点个数,子节点id
    tree[node_id] = children  # 将所有父节点保存进树中
# 记录每个深度的叶子节点数量(列表长度应为n+1因为可能出现只有左、右子树的情况)
leave_num = [0 for i in range(n + 1)]
max_depth = 0  # 最大深度决定我们最终搜索到的层数

# dfs算法搜索每层叶子结点个数
visited = {}  # 记录是否遍历过某一结点
dfs('01', 0)
print(" ".join(str(i) for i in leave_num[:max_depth + 1]))

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值