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];
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章