題目地址
https://leetcode-cn.com/problems/unique-binary-search-trees/
題目描述
給定一個整數(shù) n,求以 1 ... n 為節(jié)點組成的二叉搜索樹有多少種?
示例:
輸入: 3
輸出: 5
解釋:
給定 n = 3, 一共有 5 種不同結(jié)構(gòu)的二叉搜索樹:
1 3 3 2 1
\ / / / \ \
3 2 1 1 3 2
/ / \ \
2 1 2 3
題解
遞歸解法
定義遞歸函數(shù)
public int build(int left, int right),用來描述通過[left, right]構(gòu)建的所有二叉搜索樹的數(shù)量。
class Solution {
public int numTrees(int n) {
return build(1, n);
}
public int build(int left, int right) {
if (left == right) return 1;
if (left > right) return 1; // null 子樹也屬于一棵樹
int numTrees = 0;
for (int i = left; i <= right; ++ i) {
// [left, i-1] 表示左子樹
int numLeftTrees = build(left, i-1);
// [i+1, right] 表示右子樹
int numRightTrees = build(i+1, right);
numTrees += numLeftTrees * numRightTrees;
}
return numTrees;
}
}

耗時非常長
通過 memo 剪枝
class Solution {
public int numTrees(int n) {
int[][] memo = new int[n+1][n+1];
for (int i = 0; i <= n; i++) {
Arrays.fill(memo[i], -1);
}
return build(1, n, memo);
}
public int build(int left, int right, int[][] memo) {
if (left == right) return 1;
if (left > right) return 1; // null 子樹也屬于一棵樹
if (memo[left][right] != -1) {
return memo[left][right];
}
int numTrees = 0;
for (int i = left; i <= right; ++ i) {
// [left, i-1] 表示左子樹
int numLeftTrees = build(left, i-1, memo);
// [i+1, right] 表示右子樹
int numRightTrees = build(i+1, right, memo);
numTrees += numLeftTrees * numRightTrees;
}
memo[left][right] = numTrees;
return numTrees;
}
}

執(zhí)行時間瞬間下降。