我的PAT-ADVANCED代码仓
https://github.com/617076674/PAT-ADVANCED
原题链接
PAT-ADVANCED1004:https://pintia.cn/problem-sets/994805342720868352/problems/994805521431773184
题目描述
题目翻译
1004 数叶子
家庭层级通常由谱系树呈现。 你的工作是统计那些没有孩子的家庭成员。
输入格式:
每个输入文件包含一个测试用例。在每个测试用例中,第一行给出了两个数字:0 < N < 100,代表树中的节点个数;M( < N)代表非叶子节点个数。接下来的M行,每行都是下述格式:
ID K ID[1] ID[2] ... ID[K]
ID是一个2位数字,表示一个非叶子节点,K是该节点的孩子数量,紧跟着的是一串ID值以及该ID值对应的孩子数量。为了简便,我们假设根节点的ID值是01。
输出格式:
对每个测试用例,从根结点开始,每一层你都需要统计那些没有孩子的成员。数字必须在1行内输出,每个数字间隔一个空格,行末不得有多余空格。
这个简单的例子只有2个节点,01代表根节点,02是它的唯一孩子。因此在和01同一层的节点中,没有叶子节点。而在下一层,有一个叶子节点。因此我们需要在1行内输出0 1。
输入样例:
2 1
01 1 02
输出样例:
0 1
知识点
树的静态表示法
树的层序遍历
树的深度优先遍历
思路一
树的层序遍历
本题的关键在于一棵普通树的保存。我们采取和PAT-ADVANCED1053——Path of Equal Weight同样的思路,用静态写法,事先开一个大小不低于节点上限个数的节点数组,用vector<int>型的变量来存储数组中的索引来代替指针域。
本解决思路和LeetCode102——二叉树的层序遍历思路一模一样,只不过LeetCode102——二叉树的层序遍历中的是一颗二叉树,而本题中的数并不一定是一颗二叉树。
在满足队列不为空条件的这个外循环里,我们先记录每一层的节点个数,即此时队列中存放的节点个数,记作qSize。每出队操作qSize个节点后的统计得到的叶子节点数是同一层的叶子节点数,这样就实现了分层计数的目的。将每层的计数结果保存在一个vector<int>型的变量leaves中即可。
时间复杂度和空间复杂度都是O(N)。
C++代码
#include<iostream>
#include<vector>
#include<queue>
using namespace std;
struct node { //存放节点值及其孩子信息
int num;
vector<int> child;
};
int N, M; //节点总数,非叶子节点数
node Node[100];
vector<int> leaves; //存放每一层的叶子节点数
void levelTraversal(int root);
int main(){
scanf("%d %d", &N, &M);
int ID, K, childID;
for(int i = 0; i < M; i++){
scanf("%d %d", &ID, &K);
for(int j = 0; j < K; j++){
scanf("%d", &childID);
Node[ID].child.push_back(childID);
}
}
levelTraversal(1);
for(int i = 0; i < leaves.size(); i++){
printf("%d", leaves[i]);
if(i != leaves.size() - 1){
printf(" ");
}else{
printf("\n");
}
}
return 0;
}
void levelTraversal(int root){
queue<int> q;
q.push(root);
while(!q.empty()){
int qSize = q.size();
int levelLeaves = 0;
for(int i = 0; i < qSize; i++){
int now = q.front();
q.pop();
if(Node[now].child.size() == 0){
levelLeaves++;
}
for(int j = 0; j < Node[now].child.size(); j++){
q.push(Node[now].child[j]);
}
}
leaves.push_back(levelLeaves);
}
}
C++解题报告:
思路二
树的深度优先遍历
在深度优先遍历的时候记录其层数,并按层数对每层进行叶子节点的计数操作。当然,输出的时候我们必须要知道这棵树的深度是多少,以免漏输出或者多输出0值。
时间复杂度和空间复杂度均是O(N)。
C++代码
#include<iostream>
#include<vector>
#include<queue>
using namespace std;
struct node {
int num;
vector<int> child;
};
int N, M; //节点总数,非叶子节点数
node Node[100];
int leaves[100];//存放每一层的叶子节点数
int depth;
void dfs(int root, int level);
int main(){
fill(leaves, leaves + 100, 0);
scanf("%d %d", &N, &M);
int ID, K, childID;
for(int i = 0; i < M; i++){
scanf("%d %d", &ID, &K);
for(int j = 0; j < K; j++){
scanf("%d", &childID);
Node[ID].child.push_back(childID);
}
}
dfs(1, 0);
for(int i = 0; i <= depth; i++){
printf("%d", leaves[i]);
if(i != depth){
printf(" ");
}else{
printf("\n");
}
}
return 0;
}
void dfs(int root, int level){
if(Node[root].child.size() == 0){
leaves[level]++;
depth = max(depth, level);
return;
}
for(int i = 0; i < Node[root].child.size(); i++){
dfs(Node[root].child[i], level + 1);
}
}
C++解题报告