二叉搜索树或者是一棵空树,或者是具有下列性质的二叉树:若它的左子树不空,则左子树上所有结点的值均小于或等于它的根结点的值;若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;它的左、右子树也分别为二叉搜索树。
将一系列数字按给定顺序插入一棵初始为空的二叉搜索树,你的任务是统计结果树中最下面 2 层的结点数。
输入格式:输入在第一行给出一个正整数 N (≤1000),为插入数字的个数。第二行给出 N 个 [−1000,1000] 区间内的整数。数字间以空格分隔。
输出格式:在一行中输出最下面 2 层的结点总数。
输入样例:
9
25 30 42 16 20 20 35 -5 28
输出样例:
6
一开始的分析:想着统计2层的结点树不就相当于先统计叶子结点树然后把该叶子结点去掉,再统计一次“叶子结点”,这样两次dfs后不就相当于统计到了两层的结点数了吗,但事实很快打脸。
下面附上错误算法下的半对代码:
#include<bits/stdc++.h>
using namespace std;
int cnt;
struct Tree
{
int val;
Tree* l;
Tree* r;
};
void build(Tree* &t,int data)
{
if(t==NULL)
{
t=new Tree();
t->val=data;
t->l=NULL;
t->r=NULL;
return;
}
if(data<=t->val) build(t->l,data);
else build(t->r,data);
}
void dfs(Tree* &tt)
{
if(tt!=NULL&&tt->l==NULL&&tt->r==NULL)
{
tt=NULL;
cnt++;
return;
}
else if(tt==NULL)
return;
dfs(tt->l);
dfs(tt->r);
}
int main()
{
int n;
cin>>n;
Tree* root=NULL;
while(n--)
{
int x;
cin>>x;
build(root,x);
}
dfs(root);
dfs(root);
cout<<cnt;
return 0;
}
很显然肯定是过不了的,能对一半已经是幸运!
而错误点在于,比如:
这是在该算法下第一次dfs到第二次dfs树的情况,按这种算法,两层的结点数会变成4+2=6(黑色数字),而实际应该为5(绿色数字)!
下面为AC代码:
#include<bits/stdc++.h>
using namespace std;
int mmax;
map<int,int>cnt;//cnt[第几层] = 结点个数
struct Tree
{
int val;
Tree* l;
Tree* r;
};
void dfs(Tree* &t,int data,int level)
{
if(t==NULL)
{
t=new Tree();
t->val=data;
t->l=t->r=NULL;
cnt[level]++;
mmax=max(mmax,level);
return;
}
if(data<=t->val) dfs(t->l,data,level+1);
else dfs(t->r,data,level+1);
}
int main()
{
int n;
cin>>n;
Tree* root=NULL;
while(n--)
{
int x;
cin>>x;
dfs(root,x,1);
}
cout<<cnt[mmax]+cnt[mmax-1];
return 0;
}