平衡二叉树的个数
子问题分析
step1 数学建模
原始问题中,要求f(n)的平衡二叉树个数.
举个例子,设n = 5,设
g
(
n
)
=
二
叉
搜
索
树
个
数
g(n) = 二叉搜索树个数
g(n)=二叉搜索树个数
f
(
n
,
i
)
为
当
r
o
o
t
为
i
时
的
二
叉
搜
索
树
个
数
f(n,i) 为 当root为i时的二叉搜索树个数
f(n,i)为当root为i时的二叉搜索树个数
例如:当n = 5时,f(n,2) 为
显然的:
g
(
n
)
=
∑
i
=
1
n
(
f
(
n
,
i
)
)
g(n) = \sum_{i=1}^n(f(n,i))
g(n)=i=1∑n(f(n,i))
例如
g
(
5
)
=
f
(
5
,
1
)
+
f
(
5
,
2
)
+
f
(
5
,
3
)
+
f
(
5
,
4
)
+
f
(
5
,
5
)
g(5) = f(5,1)+f(5,2)+f(5,3)+f(5,4)+f(5,5)
g(5)=f(5,1)+f(5,2)+f(5,3)+f(5,4)+f(5,5)
step2 子问题分析
这道题的重复子问题是
g
(
1
,
2
,
3
)
=
g
(
3
)
=
g
(
2
,
3
,
4
)
=
g
(
3
,
4
,
5
)
.
.
.
g({1,2,3}) = g(3) = g({2,3,4}) = g({3,4,5})...
g(1,2,3)=g(3)=g(2,3,4)=g(3,4,5)...
数学不好无法给出证明
所以,如图
我们可以得出
f
(
5
,
2
)
=
g
(
1
)
∗
g
(
3
)
f(5,2) = g(1)*g(3)
f(5,2)=g(1)∗g(3)
也可以推测其他
f
(
5
,
3
)
=
g
(
2
)
∗
g
(
2
)
f(5,3) = g(2)*g(2)
f(5,3)=g(2)∗g(2)
从而我们使用数学归纳法可以得到
f
(
n
,
i
)
=
g
(
i
−
1
)
∗
g
(
n
−
i
)
f(n,i) = g(i - 1)*g(n - i)
f(n,i)=g(i−1)∗g(n−i)
然后,我们可以获得g(n)的完整表达式
g
(
n
)
=
∑
i
=
1
n
g
(
n
−
i
)
∗
g
(
i
−
1
)
g(n) = \sum_{ i = 1}^ng(n-i)*g(i-1)
g(n)=i=1∑ng(n−i)∗g(i−1)
step3 表达式的使用
现在这么使用这个表达式呢?
首先确定的是,这是一个递推式
则有以下步骤(使用lua比较好表达)
求取g(i)
local i = 2:n do
--求g(i)
end
求每个g(i)值
local arr = []
function _g(i):
for j = 1,i do
--此时n = i
arr[i] += arr[i - j]*arr[j - 1] -- 递推表达式求和
end
end
完整的c++代码
class Solution {
public:
int numTrees(int n) {
vector<int> arr(n+4,0);
arr[0] = 1;//空树
arr[1] = 1;//一个树
int sum = 0;
for(int i = 2;i<=n;i++){
// n = i;
//求g(i)
//g(i) = f(i,1)+f(i,2)+f(i,3)+...+f(i,i)
//local gi = 0;
//local j=1:i do
// gi+= {f(i,j) = arr[j - 1]*arr[i - j]}
//end
for(int j = 1;j<=i;j++){
arr[i] += arr[j - 1]*arr[ i - j];
}
}
return arr[n];
}
};