平衡二叉树------递推

平衡二叉树

https://ac.nowcoder.com/acm/problem/19775

根据题意,找出左右子树最大差值,这个最大值一定是通过这颗树的根节点的左右子树的差值得到的,对于左子树,我们可以令他为满二叉树,这样的节点数最多,假设深度为n,那么左子树为满二叉树的节点数图片说明 ,对于右子树,如果差值要越大,那么节点数尽可能小,我们只要求出高度差为不超过d且深度为n-d-1的平衡树的最少节点数即可,接下来上图:
假设n=8 d=2;如何构造最小的二叉树,一步一步递推,
以下全部是左右子树差值不超过d=2的平衡二叉树的最少节点画法

图片说明

深度为1

图片说明

深度为2

图片说明

深度为3

图片说明

深度为4

图片说明

深度为5
图片说明

深度为6

图片说明

深度为7

图片说明

深度为8

图片说明

上面全部图都是差值为d=2的限制
我们可以发现,对于最少节点的平衡树,深度为X的最少节点平衡树的根节点的左子树的数量是深度为X-d-1的最少节点平衡树的节点数,这里我们可以得出了递推式
图片说明 为深度是x的最少节点平衡树的节点数,得出
图片说明
图片说明
图片说明
所以我们可以对于给出的深度n,差值d,左子树为满二叉树节点数为图片说明 ,右子树是最少节点平衡二叉树,图片说明 ,两者之差就是最大值了。

#include <cctype>
#include <cfloat>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <algorithm>
#include <deque>
#include <fstream>
#include <functional>
#include <iomanip>
#include <iostream>
#include <istream>
#include <iterator>
#include <list>
#include <map>
#include <ostream>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <utility>
#include <vector>
#include <unordered_map>
#include <unordered_set>
#define ll long long
#define pll pair<long long, long long>
#define P pair<int, int>
#define PP pair<P, P>
#define eps 1e-10
#define PI 3.1415926535898
#define It set<node>::iterator
using namespace std;
const int maxn=1e3+10;
ll f[maxn];
int main() {
    ll n,m;
    cin>>n>>m;
    ll sum=1;
    if (n==0) {
        cout<<0<<endl;
        return 0;
    } else if (n==1) {
        cout<<0<<endl;
        return 0;
    }
    for (int i=1; i<n; i++) {
        sum*=2;
    }
    sum-=1;
    for (int i=1; i<=m; i++) f[i]=f[i-1]+1;
    for (int i=m+1; i<=n; i++) {
        f[i]+=f[i-1];
        f[i]+=f[i-m-1]+1;
    }
    cout<<sum-f[n-m-1]<<endl;
    return 0;
} 
全部评论

相关推荐

头像
11-18 16:08
福州大学 Java
影流之主:干10年不被裁,我就能拿别人一年的钱了,日子有盼头了
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务