96. 不同的二叉搜索树

96. 不同的二叉搜索树

1.想法

image.png

当根确定后,就是左右两边的子树的排列,这个过程相当于在处理前面处理过的结构,例如图中的n=3时,左子树分配两个,右子树分配0个,那么就相当于处理n=2的情形,而且我们发现当根为3的时候和n=2一模一样,但是当根为1时,其处理过程与n=2类似
那么我们可以得出结论我们处理过程就是一个给左右子树选择节点个数的过程,以左子树为例,其取节点个数可以从0->n-1,相应的右子树个数为n-1->0
1.备忘录算法:
我们用一维数组f[]表示我们的结果,那么f[n]代表了当取值n的时候的结果
f[n]=\sum_{i=0}^{n-1}f(i)*f(n-i-1)
当f(i)不知道时,先去求子问题f(i)的值

优化

我们发现对于一个数来说,例如3,我们只需计算以1为底的值,那么以3为底的值我们也就知道了,而对于以二为底的我们需要单独计算,放到特征值里面,那么就是说左子树为节点为0或者1计算完毕就行了,其最终结果为
1.若为偶数f(n)=2\sum_{i=0}^{n/2-1}f(i)f(n-i-1) //计算左边从分0-(n/2-1)个节点的值,右边会经历相同的变化,所以不用重复计算乘以2为最终结果
2.若为奇数f(n)=2\sum_{i=0}^{n/2-1}f(i)f(n-i-1) +f(n/2)f(n/2) //计算从0-(n/2-1),但是n/2的值没有计算,其等于f(n/2)f(n/2)左右各n/2各节点,各有f(n/2)种变化

2.动态规划

与备忘录自顶向下的算法不同,动态规划是自底向上,所以需要先计算前面的子问题,再通过前面的子问题计算现在的问题
规约公式还是:
f[n]=\sum_{i=0}^{n-1}f(i)*f(n-i-1)

2.代码:

1.备忘录算法(无优化):

public int numTrees(int n) {
       if(n==1)return 1;  
       int[] f = new int[n+1];
       f[1]=1;
       f[0]=1;
       f[n] = caculateNum(f,n);  //先去计算原问题
       return f[n];
    }

    private int caculateNum(int[] f, int n) {
        for(int i=0;i<n;i++){
            if(f[i] == 0){  //如果子问题没有解的话,先去解决子问题
                f[i]=caculateNum(f,i);   
            }
            if(f[n-i-1]==0){
                f[n-i-1]=caculateNum(f,n-i-1);
            }
            f[n]+=f[i]*f[n-i-1];  //根据子问题求出原问题
        }
        return f[n];
    }
image.png

2.备忘录算法(优化)

 public int numTrees(int n) {
       if(n==1)return 1;  
       int[] f = new int[n+1];
       f[1]=1;
       f[0]=1;
       f[n] = caculateNum(f,n);
       return f[n];
    }

     private int caculateNum(int[] f, int n) {
        for(int i=0;i<n/2;i++){    //不用计算所有的值,而是计算前一半的
            if(f[i] == 0){
                f[i]=caculateNum(f,i);
            }
            if(f[n-i-1]==0){
                f[n-i-1]=caculateNum(f,n-i-1);
            }
            f[n]+=f[i]*f[n-i-1];
        }
        return n%2==0?f[n]*2:(f[n]*2+f[n/2]*f[n/2]);
    }
image.png

3.动态规划算法

public int numTrees(int n) {
       if(n==1)return 1;
       int[] f = new int[n+1];
       f[1]=1;
       f[0]=1;
       for(int i=2;i<=n;i++){   //先计算子问题,然后再计算原问题
           for(int j=0;j<i/2;j++){
               f[i]+=f[j]*f[i-j-1];
           }
           f[i] = ((i%2==0) ? (f[i]*2) :(f[i]*2+f[i/2]*f[i/2])); 
       }
       return f[n];
   }
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 227,224评论 6 529
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 97,916评论 3 413
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 175,014评论 0 373
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 62,466评论 1 308
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 71,245评论 6 405
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 54,795评论 1 320
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 42,869评论 3 440
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 42,010评论 0 285
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 48,524评论 1 331
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 40,487评论 3 354
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 42,634评论 1 366
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 38,173评论 5 355
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 43,884评论 3 345
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 34,282评论 0 25
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 35,541评论 1 281
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 51,236评论 3 388
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 47,623评论 2 370

推荐阅读更多精彩内容