PAT-ADVANCED1004——Counting Leaves
我的PAT-ADVANCED程式碼倉:https://github.com/617076674/PAT-ADVANCED
原題連結: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個節點後的統計得到的葉子節點數是同一層的葉子節點數
時間複雜度和空間複雜度都是O(N)。
C++程式碼:
#include<iostream>
#include<vector>
#include<queue>
using namespace std;
struct node {
int num;
vector<int> child;
};
int N; //節點總數
int M; //非葉子節點數
node Node[100];
vector<int> leaves; //存放每一層的葉子節點數
void levelTraversal(int root);
int main(){
cin >> N >> M;
int ID, K, childID;
for(int i = 0; i < M; i++){
cin >> ID >> K;
for(int j = 0; j < K; j++){
cin >> childID;
Node[ID].child.push_back(childID);
}
}
levelTraversal(1);
for(int i = 0; i < leaves.size(); i++){
cout << leaves[i];
if(i != leaves.size() - 1){
cout << " ";
}
}
cout << endl;
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; //節點總數
int M; //非葉子節點數
node Node[100];
int leaves[100] = {0};//存放每一層的葉子節點數
int depth;
void dfs(int root, int level);
int main(){
cin >> N >> M;
int ID, K, childID;
for(int i = 0; i < M; i++){
cin >> ID >> K;
for(int j = 0; j < K; j++){
cin >> childID;
Node[ID].child.push_back(childID);
}
}
dfs(1, 0);
for(int i = 0; i <= depth; i++){
cout << leaves[i];
if(i != depth){
cout << " ";
}
}
cout << endl;
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++解題報告: