96. 不同的二叉搜索树
https://leetcode-cn.com/problems/unique-binary-search-trees/
解法一:dp
class Solution:
def numTrees(self, n: int) -> int:
G = [0] * (n+1)
G[0] = G[1] = 1
for i in range(2, n+1):
for j in range(1, n+1):
G[i] += G[j-1] * G[i-j]
return G[n]
解法二:递归

如上图,以3位根的组合总数为左子树形态总数 * 右子树形态总数
,即2*2=4
类似95.不同的二叉搜索树 II的思路,对区间[1...n-1]递归,每次以i(i从1~n-1)为根将区间划分为左右子树
注意,当左区间或右区间长度小于0,即无法构造子树(对应空节点)时,子树数=1而不是0
class Solution:
def numTrees(self, n: int) -> int:
def countTrees(start, end):
if start > end:
return 1
res = 0
for i in range(start, end+1):
left = countTrees(start, i-1)
right = countTrees(i+1, end)
res += left * right
return res
return countTrees(1, n)
然而超时,当n=19
改进
上面暴力递归穷举会重复计算,例如[1...2]这个区间会重复计算多次,而该区间的结果一旦计算出来是不变的,考虑使用备忘录
class Solution:
def numTrees(self, n: int) -> int:
memo = [[0]*(n+1) for _ in range(n+1)]
def countTrees(start, end):
if start > end:
return 1
if memo[start][end] != 0: #备忘录有记录,直接返回
return memo[start][end]
res = 0
for i in range(start, end+1):
left = countTrees(start, i-1)
right = countTrees(i+1, end)
res += left * right
memo[start][end] = res #得到结果写备忘录
return res
return countTrees(1, n)
最后更新于