一、概述
25分题,正常来讲应该45分钟之内做完,我用了快90分钟,日日了狗不说,还没AC。
究其原因,在于我做这道题时,只想着从最直观的角度出发,用人脑的方式,也就是我平常的判断方式,判断一棵树是否是完全二叉树,这是不行的,按我的方法:
先建树;
BFS得到各节点层数以及每层的节点,按顺序;
BFS得到树高;
根据树高,先从第一层到倒数第二层,看节点数量是不是满的;
若不是满的,则不是完全二叉树;
若是满的,则看倒数第二层;
分四种情况:
左右皆不空,左右皆空,左空右不空,左不空右空;
按照层中节点的顺序往右,第一种在之前出现过空的时候可以return,第二种若前边不空则置标志位为空;第三种同第二种;第四种直接return。
太麻烦了。我同时维护了近十个数组,活生生把算法题做成了模拟题。
实际上,应该按如下方法做:
首先建树。建完后给所有节点编号,假装是完全二叉树的那种编号,就是根节点是n,左孩子2n右孩子2n+1。然后看最大的编号是不是和节点数量相同,相同则是完全二叉树,否则不是。
以样例的第二个为例,他不是完全二叉树。因为7的编号为7,0的编号为8,6的编号为9,这样一来,最大编号9大于总数8。说明不是。简单得多。
使用DFS给节点编号。
二、分析
虽然我这个特别蠢,可是往好了想,也是练习了BFS、层数、求各层节点嘛。(还是太蠢了,蠢哭了)
下面分析AC代码。
首先是输入,选择使用静态树。也就是开一个节点数组,往里面存,不使用指针。如下:
struct Node
{
int root=0;
int lchild=-1,rchild=-1;
};
Node BitTree[25];
然后使用一个数组记录哪些节点不可能是根节点——那些出现在孩子节点的就肯定不是了。然后输入:
发现输入可能有两种,一种是0到9,一种是-;
因此使用string输入,并与-比较,不是-那就使用stoi将string转为int。
注意,stoi函数使用要事先将编译设置好,工具,编译选项,设置,生成代码,语言标准,c++11,不然会报错。
然后输入即可。如下:
for(int i=0;i<N;i++)
{
string l,r;
int lchild;
int rchild;
cin>>l;
cin>>r;
if(l=="-")
lchild=-1;
else
lchild=stoi(l);
if(r=="-")
rchild=-1;
else
rchild=stoi(r);
if(lchild==-1)
BitTree[i].lchild=-1;
else
{
BitTree[i].lchild=lchild;
rootNode[lchild]=0;
}
if(rchild==-1)
BitTree[i].rchild=-1;
else
{
BitTree[i].rchild=rchild;
rootNode[rchild]=0;
}
}
输入的同时也就把根节点筛出来了。
然后使用DFS进行编号。由于编号随DFS变化,所以要作为参数输入。
每在DFS中调用一次DFS,编号乘二或者乘二加一,保存最大编号和最大编号对应的节点序号。最大序号是输出的时候要用到的。如下:
void DFS(int root,int index)
{
if(index>maxindex)
{
ans=root;
maxindex=index;
}
if(BitTree[root].lchild!=-1)
DFS(BitTree[root].lchild,index*2);
if(BitTree[root].rchild!=-1)
DFS(BitTree[root].rchild,index*2+1);
}
利用的是完全二叉树左孩子序号为本身序号二倍,右孩子序号为二倍加一。
然后判断并输出。
三、总结
当看到题时,首先思考有无可利用的性质,不要直接开始模拟,太蠢了。
遇到的坑点有以下几个:
fill给二维数组赋值时,参数为a[0],a[0]+m*n,x,不加[0]是不行的。
二维数组的第一个表示第几行,第二个表示第几列。
以string输入时,判断字符串相等一定要用string==“”,用双引号而不是单引号。即是只有一个字符。
string转换为int时可以使用stoi函数,我自己傻不拉几写了一个,好蠢。
PS:我的代码:未AC,懒得debug了,心力交瘁
#include<stdio.h>
#include<cstdio>
#include<iostream>
#include<string>
#include<cstring>
#include<vector>
#include<map>
#include<math.h>
#include<queue>
#include<algorithm>
using namespace std;
struct Node
{
int root=0;
int lchild=-1,rchild=-1;
int level=0;
};
Node BitTree[25];
int rootNode[25];
int vis[25]={0};
int levelNode[10][10];
int levelnum[7]={0};
int level[7]={0,1,2,4,8,16,32};
int last=0;
void BFS(int root,int level)
{
queue<int> q;
q.push(root);
BitTree[root].level=level;
vis[root]=1;
while(!q.empty())
{
int front=q.front();
last=front;
levelNode[BitTree[front].level][levelnum[BitTree[front].level]]=front;
levelnum[BitTree[front].level]++;
q.pop();
if(BitTree[front].lchild!=-1&&vis[BitTree[front].lchild]==0)
{
BitTree[BitTree[front].lchild].level=BitTree[front].level+1;
q.push(BitTree[front].lchild);
vis[BitTree[front].lchild]=1;
}
if(BitTree[front].rchild!=-1&&vis[BitTree[front].rchild]==0)
{
BitTree[BitTree[front].rchild].level=BitTree[front].level+1;
q.push(BitTree[front].rchild);
vis[BitTree[front].rchild]=1;
}
}
}
int sti(string num)
{
int sum=0;
string::reverse_iterator it;
int index=0;
for(it=num.rbegin();it!=num.rend();it++)
{
sum+=(*it-'0')*pow(10,index);
index++;
}
return sum;
}
int main()
{
fill(rootNode,rootNode+25,1);
fill(levelNode[0],levelNode[0]+36,-1);
int N;
scanf("%d",&N);
for(int i=0;i<N;i++)
{
string l,r;
int lchild;
int rchild;
cin>>l;
cin>>r;
if(l=="-")
lchild=-1;
else
lchild=sti(l);
if(r=="-")
rchild=-1;
else
rchild=sti(r);
if(lchild==-1)
BitTree[i].lchild=-1;
else
{
BitTree[i].lchild=lchild;
rootNode[lchild]=0;
}
if(rchild==-1)
BitTree[i].rchild=-1;
else
{
BitTree[i].rchild=rchild;
rootNode[rchild]=0;
}
}
int root;
for(int i=0;i<N;i++)
{
if(rootNode[i]==1)
{
root=i;
break;
}
}
BFS(root,1);
int maxlevel=0;
for(int i=0;i<N;i++)
{
if(BitTree[i].level>maxlevel)
{
maxlevel=BitTree[i].level;
}
}
int valid=1;
if(N<level[maxlevel])
{
printf("NO %d",root);
return 0;
}
else
{
int childNull=0;
int i;
for(i=1;i<maxlevel;i++)
{
if(levelnum[i]!=level[i])
{
printf("NO %d",root);
return 0;
}
}
for(int j=0;j<levelnum[maxlevel-1];j++)
{
i=levelNode[maxlevel-1][j];
if(BitTree[i].level==maxlevel-1)//如果他是最下面一层上面的一层
{
if(BitTree[i].lchild==-1&&BitTree[i].rchild!=-1)//左空右不空
{
printf("NO %d",root);
return 0;
}
else if(BitTree[i].lchild!=-1&&BitTree[i].rchild!=-1)//左右都不空
{
if(childNull==1)
{
printf("NO %d",root);
return 0;
}
else
continue;
}
else if(BitTree[i].lchild!=-1&&BitTree[i].rchild==-1)
{
if(childNull==1)
{
printf("NO %d",root);
return 0;
}
else
childNull=1;
}
else
{
childNull=1;
}
}
}
printf("Yes %d",last);
}
}
AC代码如下:
#include<stdio.h>
#include<cstdio>
#include<iostream>
#include<string>
#include<cstring>
#include<vector>
#include<map>
#include<math.h>
#include<queue>
#include<algorithm>
using namespace std;
struct Node
{
int root=0;
int lchild=-1,rchild=-1;
};
Node BitTree[25];
int rootNode[25];
int maxindex=-1;
int ans=-1;
void DFS(int root,int index)
{
if(index>maxindex)
{
ans=root;
maxindex=index;
}
if(BitTree[root].lchild!=-1)
DFS(BitTree[root].lchild,index*2);
if(BitTree[root].rchild!=-1)
DFS(BitTree[root].rchild,index*2+1);
}
int main()
{
fill(rootNode,rootNode+25,1);
int N;
scanf("%d",&N);
for(int i=0;i<N;i++)
{
string l,r;
int lchild;
int rchild;
cin>>l;
cin>>r;
if(l=="-")
lchild=-1;
else
lchild=stoi(l);
if(r=="-")
rchild=-1;
else
rchild=stoi(r);
if(lchild==-1)
BitTree[i].lchild=-1;
else
{
BitTree[i].lchild=lchild;
rootNode[lchild]=0;
}
if(rchild==-1)
BitTree[i].rchild=-1;
else
{
BitTree[i].rchild=rchild;
rootNode[rchild]=0;
}
}
int root;
for(int i=0;i<N;i++)
{
if(rootNode[i]==1)
{
root=i;
break;
}
}
DFS(root,1);
if(maxindex>N)
{
printf("NO %d",root);
}
else
printf("YES %d",ans);
}