题目地址
https://www.patest.cn/contests/pat-a-practise/1110
题目描述
Given a tree, you are supposed to tell if it is a complete binary tree.
Input Specification:
Each input file contains one test case. For each case, the first line gives a positive integer N (<=20) which is the total number of nodes in the tree – and hence the nodes are numbered from 0 to N-1. Then N lines follow, each corresponds to a node, and gives the indices of the left and right children of the node. If the child does not exist, a “-” will be put at the position. Any pair of children are separated by a space.
Output Specification:
For each case, print in one line “YES” and the index of the last node if the tree is a complete binary tree, or “NO” and the index of the root if not. There must be exactly one space separating the word and the number.
Sample Input 1:
9
7 8
- -
- -
- -
0 1
2 3
4 5
- -
- -
Sample Output 1:
YES 8
Sample Input 2:
8
- -
4 5
0 6
- -
2 3
- 7
- -
- -
Sample Output 2:
NO 1
思路
完全二叉树 定义与性质
若设二叉树的深度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第 h 层所有的结点都连续集中在最左边,这就是完全二叉树。
完全二叉树是由满二叉树而引出来的。对于深度为K的,有n个结点的二叉树,当且仅当其每一个结点都与深度为K的满二叉树中编号从1至n的结点一一对应时称之为完全二叉树。
一棵二叉树至多只有最下面的一层上的结点的度数可以小于2,并且最下层上的结点都集中在该层最左边的若干位置上,则此二叉树成为完全二叉树。
本题我按照第二点来做的,就是得到树根,然后利用队列,给节点编号,编号必须有且只有1-n,否则就不是完全二叉树。
ac1
某个节点的入度为0,表示是根节点
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <iostream>
#include <string>
#include <vector>
#include <queue>
#include <algorithm>
#include <sstream>
using namespace std;
const int INF = 0x7fffffff;
const int N = 22;
int n;
struct data{
int no; // 编号
int left;
int right;
};
int in_degree[N];
data v[N];
int rootNum;
int main(int argc, char const *argv[])
{
// freopen("in.txt", "r", stdin);
while(scanf("%d",&n) != EOF)
{
string s1,s2;
for(int i=0;i<n;i++)
{
in_degree[i] = 0;
}
for(int i=0;i<n;i++)
{
cin >> s1 >> s2;
if(s1 == "-"){
v[i].left = -1;
}else{
stringstream ss;
ss << s1;
ss >> v[i].left;
in_degree[v[i].left] ++;
}
if(s2 == "-"){
v[i].right = -1;
}else{
stringstream ss;
ss << s2;
ss >> v[i].right;
in_degree[v[i].right] ++;
}
}
for(int i=0;i<n;i++)
{
if(in_degree[i]== 0)
rootNum = i;
}
v[rootNum].no = 1;
queue<int> que;
que.push(rootNum);
while(!que.empty())
{
int fa = que.front();
que.pop();
if(v[fa].left != -1)
{
int leftNum = v[fa].left;
v[leftNum].no = v[fa].no * 2;
que.push(leftNum);
}
if(v[fa].right != -1)
{
int rightNum = v[fa].right;
v[rightNum].no = v[fa].no * 2 + 1;
que.push(rightNum);
}
}//
int lastNode;
bool flag = true;
for(int i=0;i<n;i++)
{
if(v[i].no > n)
flag = false;
if(v[i].no == n)
lastNode = i;
}
if(flag){
printf("YES %d\n",lastNode);
}else{
printf("NO %d\n",rootNum);
}
}
return 0;
}
ac 2,
并查集判断树根,然后构造出二叉树来
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <iostream>
#include <string>
#include <vector>
#include <queue>
#include <algorithm>
#include <sstream>
#include <list>
#include <stack>
#include <map>
#include <set>
#include <iterator>
#include <unordered_map>
using namespace std;
const int INF = 0x7fffffff;
typedef long long int LL;
const int N = 20 + 5;
int n;
struct data{
int id;
int left;
int right;
};
typedef struct node
{
int val;
struct node* left;
struct node* right;
node(int _val = -1)
{
val = _val;
left = NULL;
right = NULL;
}
}Bnode;
int str2int(string s)
{
stringstream ss;
ss << s;
int t;
ss >> t;
return t;
}
data v[N];
int fa[N];
int Find(int x)
{
if(x == fa[x])
return x;
return fa[x] = Find(fa[x]);
}
void Merg(int x,int y)
{
int xx = Find(x);
int yy = Find(y);
fa[yy] = xx;
}
Bnode* Create(int id)
{
if(id > n)
return NULL;
Bnode* rt = new Bnode(id);
if(v[id].left != -1)
rt->left = Create(v[id].left);
else
rt->left = NULL;
if(v[id].right != -1)
rt->right = Create(v[id].right);
else
rt->right = NULL;
return rt;
}
int main()
{
//freopen("in.txt", "r" , stdin);
while(scanf("%d", &n) != EOF)
{
for(int i=0;i<n;i++)
fa[i] = i;
for(int i=0;i<n;i++)
{
string s1,s2;
cin >> s1 >> s2;
int leftVal,rightVal;
if(s1 == "-")
leftVal = -1;
else
{
leftVal = str2int(s1);
if(Find(i) != Find(leftVal)){
Merg(i, leftVal);
}
}
if(s2 == "-")
rightVal = -1;
else
{
rightVal = str2int(s2);
if(Find(i) != Find(rightVal)){
Merg(i, rightVal);
}
}
v[i].id = i;
v[i].left = leftVal;
v[i].right = rightVal;
}
set<int> se;
for(int i= 0;i<n;i++)
{
se.insert(Find(i));
}
int rtNum = *se.begin();
Bnode *root = Create(rtNum);
queue<Bnode*> que;
queue<int> queId;
que.push(root);
queId.push(1);
bool flag = true;
int maxTmp = -1;
int ans ;
while(!que.empty())
{
Bnode* bt = que.front();
que.pop();
int index = queId.front();
queId.pop();
if(index > n)
{
flag = false;
}
if(index > maxTmp)
{
maxTmp = index;
ans = bt->val;
}
if(bt->left != NULL)
{
que.push(bt->left);
queId.push( 2 * index);
}
if(bt->right != NULL)
{
que.push(bt->right);
queId.push( 2 * index + 1);
}
}
if(flag)
{
printf("YES ");
printf("%d", ans);
}
else{
printf("NO ");
printf("%d", rtNum);
}
printf("\n");
}
return 0;
}