初拿到这题时,很自然的就想到用递归来做。
然后就有了下面的解法,最终执行没问题,只是超时了,明天优化一下。
public class Solution {
public int numTrees(int n) {
if (n == 1) {
return 1;
}
int res = 0;
for (int i = 1; i <= n; i++) {
// 把 i 当成父节点
int left = compute(i, 1, i - 1, 0);
int right = compute(i, i + 1, n, 1);
res += left != 0 && right != 0 ? left * right : (left != 0 ? left : right);
}
return res;
}
// 大问题拆解成小问题来做就很棒
private int compute(int father, int begin, int end, int turn) {
if (begin > end) {
return 0;
}
// 0 左子树 1 右子树
if (begin == end) {
return 1;
}
int lenMin = 0;
int lenMax = 0;
if (turn == 0) {
// 左子树
lenMax = father - 1;
} else {
// 右子树
lenMin = father + 1;
}
int left = 0, right = 0;
int res = 0;
for (int i = begin; i <= end; i++) {
left = 0;
right = 0;
// 这一步是选择子节点来的
if (turn == 0) {
// 左子树
left += compute(i, begin, i - 1, 0);
// 右子树
right += compute(i, i + 1, lenMax, 1);
} else {
// 左子树
left += compute(i, lenMin, i - 1, 0);
// 右子树
right += compute(i, i + 1, end, 1);
}
res += left != 0 && right != 0 ? left * right : (left != 0 ? left : right);
}
return res;
}
}
看了一下时间,现在是凌晨12点18分,已经到了明天了,所以我试着优化了一下,主要就是存储递归过程中的一些数值,减少了重复计算。
这次没有超时
public class Solution {
private static Map<String, Integer> map = new HashMap<>();
public int numTrees(int n) {
if (n == 1) {
return 1;
}
int res = 0;
for (int i = 1; i <= n; i++) {
// 把 i 当成父节点
int left = compute(i, 1, i - 1, 0);
int right = compute(i, i + 1, n, 1);
res += left != 0 && right != 0 ? left * right : (left != 0 ? left : right);
}
return res;
}
// 大问题拆解成小问题来做就很棒
private int compute(int father, int begin, int end, int turn) {
if (begin > end) {
return 0;
}
// 0 左子树 1 右子树
if (begin == end) {
return 1;
}
int lenMin = 0;
int lenMax = 0;
if (turn == 0) {
// 左子树
lenMax = father - 1;
} else {
// 右子树
lenMin = father + 1;
}
int left = 0, right = 0;
int res = 0;
for (int i = begin; i <= end; i++) {
left = 0;
right = 0;
// 这一步是选择子节点来的
if (turn == 0) {
// 左子树
int tempLeft = map.get("left:" + (i - 1 - begin)) == null ? compute(i, begin, i - 1, 0) : map.get("left:" + (i - 1 - begin));
left += tempLeft;
map.put("left:" + (i - 1 - begin), tempLeft);
// 右子树
int tempRight = map.get("right:" + (lenMax - i - 1)) == null ? compute(i, i + 1, lenMax, 1) : map.get("right:" + (lenMax - i - 1));
right += tempRight;
map.put("right:" + (lenMax - i - 1), tempRight);
} else {
// 左子树
int tempLeft = map.get("left:" + (i - 1 - lenMin)) == null ? compute(i, lenMin, i - 1, 0) : map.get("left:" + (i - 1 - lenMin));
left += tempLeft;
map.put("left:" + (i - 1 - lenMin), tempLeft);
// 右子树
int tempRight = map.get("right:" + (end - i - 1)) == null ? compute(i, i + 1, end, 1) : map.get("right:" + (end - i - 1));
right += tempRight;
map.put("right:" + (end - i - 1), tempRight);
}
res += left != 0 && right != 0 ? left * right : (left != 0 ? left : right);
}
return res;
}
}