不同的二叉搜索树的种数数量 C/C++ 动态规划

#if 0
class Solution {
public:
    int numTrees(int n) {
        vector<int> s(n+1);   // 取值范围有n个数,取n个数范围内的任意一个树做根节点的二叉搜索树的种数的和
        /** 那么对于任意数 i 做 根节点,那么 i 的左侧 有i-1个数,这么多数会有s[i-1] 种二叉树,右侧有 j-i 个数,有s[j-i]种二叉树的排列方式,
        将两者相乘,然后累加不同取值i时的情况,就得到递推公式
        **  有递推公式 S[j] = 累加{sum[i-1] * sum[j-i]} ,1<=i<=j , 1<=j<=n  i 为不同的根节点的取值,j 为数的多少
        **/
        //初始化数组
        s[0] = 1;  //表示没有数据时的二叉树的种数,很显然,这也属于一种情况,只有一个数的二叉树的种数为1.
        s[1] = 1;
        for(int j = 2; j <=n ; j++){
            for(int i = 1; i <= j;i++){
                s[j] +=s[i-1] * s[j-i];
            }
        }
        return s[n];
    }
};
#endif

#if 0
class Solution {
public:
    int numTrees(int n) {
        vector<vector<int>> Gemm(n+1,vector<int>(n+1,0));  // i, j  表示根节点取i值时,二叉搜索树有 j 个数二叉搜索的种数
        /**需要的结果是根节点取值为所有n个数范围内的任意一个数i的二叉树的种树的和
        **即需要 累加{Gemm[i][n]}  1<=i<=n
        ** 每一个Gemm[i][j] = 累加{Gemm[k][i-1]}  *  累加{Gemm[l][j-i]}
        * 所以 递推式是Gemm[i][j]}  = 累加{Gemm[k][i-1]} * 累加{Gemm[l][j-i]}   1<=i<=j ; 1<=j<=n; 1<=k<=i; 1<=l<=j-i;
        ** 
        **/
        //初始化数组
        Gemm[1][1] = 1;
        Gemm[1][0] = 1;
        for(int j = 1; j <=n ; j++){
            for(int i = 1; i <= j;i++){    
                int sum1=0,sum2=0;
                for(int k = 1; k<=i-1;k++){
                    sum1+=Gemm[k][i-1];
                }
                for(int l = 1; l<=j-i;l++){
                    sum2+=Gemm[l][j-i];
                }
                if(!sum1) sum1 = 1;
                if(!sum2) sum2 = 1;
                Gemm[i][j] = sum1*sum2;
            }
        }
        int sum0=0;
        for(int i = 1; i<= n;i++){
            sum0+=Gemm[i][n];
        }
        return sum0;
    }
};
#endif

#if 1
class Solution {
public:
    int numTrees(int n) {
        vector<vector<int>> Gemm(n+1,vector<int>(n+1,0));  // i, j  表示根节点取i值时,二叉搜索树有 j 个数二叉搜索的种数
        /**
        * 递推式是Gemm[i][j]}  = 累加{Gemm[k][i-1]} * 累加{Gemm[l][j-i]}   1<=i<=j ; 1<=j<=n; 1<=k<=i; 1<=l<=j-i;
        ** 如果这样会有j,i,(k,l) 三层变量的变化,会有三层循环,时间复杂度在n3 但是对于大多数 累加{Gemm[k][i-1]} 和 累加{Gemm[l][j-i]} 都已经计算过,想办法把它们保存下来,使用一个S[j] 来保存 有j个数的二叉树的种数。
        **/
        //初始化数组
        vector<int> S(n+1);
        Gemm[1][1] = 1;
        Gemm[1][0] = 1;
        S[0] = 1;
        S[1] = 1;
        for(int j = 1; j <=n ; j++){
            for(int i = 1; i <= j;i++){    
                int sum1=0,sum2=0;
                if(S[i-1]) sum1 = S[i-1];
                else{
                    for(int k = 1; k<=i-1;k++){
                        sum1+=Gemm[k][i-1];
                    }
                }
                if(S[j-i]) sum2 = S[j-i];
                else{
                    for(int l = 1; l<=j-i;l++){
                        sum2+=Gemm[l][j-i];
                    }
                }
                if(!sum1) sum1 = 1;
                if(!sum2) sum2 = 1;
                Gemm[i][j] = sum1*sum2;
            }
        }
        int sum0=0;
        for(int i = 1; i<= n;i++){
            sum0+=Gemm[i][n];
        }
        return sum0;
    }
};
#endif
posted @ 2022-09-25 21:28  danieldai  阅读(37)  评论(0编辑  收藏  举报