平衡二叉树(AVL树),是指左右子树高度差至多为1的二叉树,并且该树的左右两个子树也均为AVL树。 现在问题来了,给定AVL树的节点个数n,求有多少种形态的AVL树恰好有n个节点。
Input
一行,包含一个整数n。 (0 < n <= 2000)
Output
一行表示结果,由于结果巨大,输出它对1000000007取余数的结果。
Input示例
10
Output示例
60
n个结点最高为log1.68(n),最低为log2n,dp[i][h] 为i个结点高度为h的个数。
dp[i][j] 可分为三种情况:①左右子树高度相同:dp[j][h-1]*dp[i-1-j][h-1];
②左右子树高度差一:dp[i][h-1]*dp[i-1-j][h-2];
③左右子树高度差一:dp[i][h-2]*dp[i-1-j][h-1] (②③两种情况相同可直接乘二)
需要注意:dp[0][0]和dp[1][1] 后续乘法会用到,所以初始化的时候必须改为1!
n个节点的情况为高度为h1,h2,h3,h4... 因此将结点为n,高度为2-h的所有dp相加。
中间不要忘记 正! 确! 的! 取余
注意 j,h的范围数组下标0 - MAX
#include<iostream>
#include<cstring>
using namespace std;
const int mod = 1000000007;
const int MAX_N = 2000;
int n;
long long dp[MAX_N + 5][25];
void solve()
{
int h;
int sum = 0;
memset(dp,0,sizeof(dp));
dp[0][0] = 1;
dp[1][1] = 1;
for(int i = 2; i <= n; i++)
for(int j = 0; j < i; j++)
for(h = 2; h <= 20; h++)
{
dp[i][h] += dp[j][h-1] * dp[i-j-1][h-1]%mod; //开始没写 +
dp[i][h] += 2*dp[j][h-1]*dp[i-j-1][h-2]%mod;
dp[i][h] %= mod;
}
for(int i = 0; i <= h; i++)
{
sum += dp[n][i];
sum %= mod; // 这里取余
}
cout<<sum<<endl;
}
int main()
{
cin>>n;
solve();
return 0;
}