持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第13天,点击查看活动详情
动态规划(Dynamic Programming)是一种分阶段求解决策问题的数学思想,它通过把原问题分解为简单的子问题来解决复杂问题。
不同的二叉搜索树
给你一个整数 n ,求恰由 n 个节点组成且节点值从 1 到 n 互不相同的 二叉搜索树 有多少种?返回满足题意的二叉搜索树的种数。
示例 1:
输入:n = 3 输出:5
示例 2:
输入:n = 1 输出:1
二叉搜索树
它或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为二叉搜索树。
思路:
把第i个节点看作是根节点, 那么所产生的所有可能性为 左子树的所有可能性 * 右子树所有可能性 当根节点为i的时候, 左边为 n - 1 个节点所形成的子树,右边为 n - i 个节点所形成的子树, 假设dp[i]表示为有多少个节点所形成的子树,k[i] 表示第i个节点为根节点的可能性。 k[i] = dp[i - 1] * dp[n - i] dp[i] = k[1] + k[2]......k[i]
依题可知:
- 当 n = 0 时,没有数字,只能形成一种满足题意的二叉搜索树 :空树。
- 当 n = 1 时,只有一个数字,只能形成一种满足题意的二叉搜索树 :单个节点。
代码如下:
fun numTrees(n: Int): Int {
val dp = IntArray(n + 1)
dp[0] = 1
for (i in 1..n) {
var count = 0
for (j in 1..i) {
count += dp[j - 1] * dp[i - j]
}
dp[i] = count
}
return dp[n]
}
- 时间复杂度 : O(n^2),需要遍历两次。
- 空间复杂度 : O(n)。我们需要 O(n) 的空间存储dp数组。