LeetCode 96.不同的二叉搜索树(卡特兰数列)

题目描述

在这里插入图片描述

记忆化搜索

对于每个节点而言都可以在区间1到n中取一个数作为根节点,比如这里取i,则左子树能在根节点1 – i - 1中取值作为根节点,右子树能在i + 1 – n中取值作为根节点。最后当前节点能取的可能就是左右子树能取可能情况的乘积。对于子树节点我们可以以同样的方式递归地去求。由于这样会有很多重复的计算,所以我们用一个map来记录已经计算过的结果,避免重复计算,这就是记忆化搜索。

    unordered_map<string,int> mp;
    int numTrees(int n) {
        return dfs(1, n);
    }
    
    int dfs(int s, int e)
    {
        string key = to_string(s)+"#"+to_string(e);
        if(mp.find(key) != mp.end()) return mp[key];
        if(s > e) return 1;
        int rs = 0;
        for(int i = s; i <= e; i++)
            rs += dfs(s,i-1) * dfs(i+1,e);
        mp.insert({key, rs});
        return rs;
    }

卡特兰数列

卡特兰数列百科
假设n个节点存在二叉排序树的个数是G(n),令f(i)为以i为根的二叉搜索树的个数,则
G(n) = f(1) + f(2) + f(3) + f(4) + … + f(n)

当i为根节点时,其左子树节点个数为i-1个,右子树节点为n-i,则
f(i) = G(i-1)*G(n-i)

综合两个公式可以得到 卡特兰数 公式
G(n) = G(0)G(n-1) + G(1)(n-2) +…+ G(n-1)*G(0)

	int numTrees(int n)
    {
        vector<int> dp(n+1);
        dp[0] = 1;
        dp[1] = 1;
        
        for(int i = 2; i < n + 1; i++)
            for(int j = 1; j < i + 1; j++) 
                dp[i] += dp[j-1] * dp[i-j];
        
        return dp[n];
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章