什麼是卡特蘭數?
卡特蘭數是組合數學中一個常出現在各種計數問題中出現的數列。其公式爲 :c(n)=c(2)*c(n-1)+c(3)*c(n-2)+...c(n-1)*c(2)。
假設n個節點存在
- 令G(n)的從1到n可以形成二叉排序樹個數
- 令f(i)爲以i爲根的二叉搜索樹的個數
即有:G(n) = f(1) + f(2) + f(3) + f(4) + ... + f(n)
n爲根節點,當i爲根節點時,其左子樹節點個數爲[1,2,3,...,i-1],右子樹節點個數爲[i+1,i+2,...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)
即:
接下來看幾個應用題:
1、不同的二叉搜索樹
給定一個整數 n,求以 1 ... n 爲節點組成的二叉搜索樹有多少種?
輸入: 3
輸出: 5
解釋: 給定 n = 3, 一共有 5 種不同結構的二叉搜索樹:
1 3 3 2 1
\ / / / \ \
3 2 1 1 3 2
/ / \ \
2 1 2 3
來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/unique-binary-search-trees/
動態規劃:
1、初始化]dp=[0,⋯,0],長度爲n+1,保存n0,⋯,n的卡特蘭數。初始化dp[0]=1,表示沒有節點, dp[1]=1,表示只有一個節點的二叉搜索樹的種類。
2、遍歷dp數組,i遍歷區間[2,n+1):
- 計算卡特蘭數,j遍歷區間[0,i)
- 由卡特蘭數公式:dp[i]+=dp[j]*dp[i-j-1]
3、返回dp[n]dp[n]
def generateTrees(n):
if n == 0:
return 0
dp = [0] * (n + 1)
dp[0] = 1
dp[1] = 1
for i in range(2, n + 1):
for j in range(i):
dp[i] += dp[j] * dp[i - j - 1]
return dp[-1]
2、不同的二叉搜索樹 II
給定一個整數 n,生成所有由 1 ... n 爲節點所組成的二叉搜索樹。
輸入: 3
輸出:
[ [1,null,3,2],
[3,2,null,1],
[3,1,null,null,2],
[2,1,3],
[1,null,2,null,3]]
來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/unique-binary-search-trees-ii/
二叉搜索樹, 一節點大於左子樹節點, 小於右子樹節點
所以我們節點是從1
到n
,當一個節點爲val
那麼它的左邊是<= val
,右邊是>=val
,
def generateTrees1(n):
if n == 0:
return []
@functools.lru_cache(None)
def dfs(start, end):
res = []
if start > end:
res.append(None)
for val in range(start, end + 1):
for left in dfs(start, val - 1):
for right in dfs(val + 1, end):
root = TreeNode(val)
root.left = left
root.right = right
res.append(root)
return res
return dfs(1, n)
——————————————————————————————
參考: