题目描述:
给定一个整数 n,生成所有由 1 ... n 为节点所组成的 二叉搜索树 。
今日学习:
1.递归
题解:
1.前两天做了96题是只要求输出数量,动规轻轻松松,就没看递归的题解,今天一思考动规的话太复杂了,临时想的递归,思路对了没实现好
2.3.和我的思路一致,实现方式稍有不同
4.记忆化递归
5.动规(果然复杂)
/**
* Definition for a binary tree node.
* function TreeNode(val, left, right) {
* this.val = (val===undefined ? 0 : val)
* this.left = (left===undefined ? null : left)
* this.right = (right===undefined ? null : right)
* }
*/
/**
* @param {number} n
* @return {TreeNode[]}
*/
// 初步思路,遍历数字,左右建树,暂告失败【不用把节点传进creatTree去,传数字就行了】
var generateTrees = function(n) {
const nodes = new Array(n)
for(let i = 0; i < n; i++) {
let node = new TreeNode(i + 1)
nodes.push(node)
}
function creatTree(nodes) {
if(nodes.length == 0) return [null]
if(nodes.length == 1) return [nodes[0]]
let C = [1, 1, 2, 5, 14, 42, 132, 429, 1430]
const res = new Array(C[nodes.length])
for(let i = 0; i < nodes.length; i++) {
let left = creatTree(nodes.slice(0, i))
let right = creatTree(nodes.slice(i + 1))
if(left.length && right.length){
for(let j = 0; j < left.length; j++) {
for(let k = 0; k < right.length; k++) {
let temp = nodes[i]
nodes[i].left = left[j]
nodes[i].right = right[k]
res.push(nodes[i])
nodes[i] = temp
}
}
}else if(left.length && !right.length) {
for(let j = 0; j < left.length; j++) {
let temp = nodes[i]
nodes[i].left = left[j]
res.push(nodes[i])
nodes[i] = temp
}
}else if(!left.length && right.length) {
for(let k = 0; k < right.length; k++) {
let temp = nodes[i]
nodes[i].right = right[k]
res.push(nodes[i])
nodes[i] = temp
}
}
}
return res
}
return creatTree(nodes)
};
// 思路同上,但是给生成树函数的参数是数字数组而不是节点数组
var generateTrees = function(n) {
const nArr = new Array(n)
for(let i = 0; i < n; i++) {
nArr[i] = i + 1
}
const buildTreeArr = (arr) => {
//0,1,2三种特殊情况特殊考虑
let treeArr = [], t = new TreeNode();
if (!arr.length) {
return [];
} else if (arr.length === 1) {
t.val = arr[0];
treeArr.push(t);
return treeArr;
} else if (arr.length === 2) {
t.val = arr[1];
t.left = new TreeNode(arr[0]);
treeArr.push(t);
t = new TreeNode(arr[0]);
t.right = new TreeNode(arr[1]);
treeArr.push(t);
return treeArr;
}
arr.forEach((val, idx, array) => {
let leftTreeArr = buildTreeArr(array.slice(0, idx));
let rightTreeArr = buildTreeArr(array.slice(idx + 1, array.length));
if (leftTreeArr.length && rightTreeArr.length) {
leftTreeArr.forEach(leftNode => {
rightTreeArr.forEach(rightNode => {
t = new TreeNode(val);
if (leftNode) t.left = leftNode;
if (rightNode) t.right = rightNode;
treeArr.push(t);
})
});
} else if (leftTreeArr.length && !rightTreeArr.length) {
leftTreeArr.forEach(leftNode => {
t = new TreeNode(val);
if (leftNode) t.left = leftNode;
treeArr.push(t);
});
} else if (!leftTreeArr.length && rightTreeArr.length) {
rightTreeArr.forEach(rightNode => {
t = new TreeNode(val);
if (rightNode) t.right = rightNode;
treeArr.push(t);
});
}
})
return treeArr;
}
return buildTreeArr(nArr);
};
// 思路还是差不多,但是不需要传数组,因为紧邻有序,所以只传数组的首末数字就行了
var generateTrees = function (n) {
function buildTree(start, end) {
let ans = [];
if (start > end) return [null];
for (let i = start; i <= end; i++) {
let leftNodes = buildTree(start, i - 1);
let rightNodes = buildTree(i + 1, end);
for (const leftNode of leftNodes) {
for (const rightNode of rightNodes) {
let cur = new TreeNode(i);
cur.left = leftNode;
cur.right = rightNode;
ans.push(cur);
}
}
}
return ans;
}
if (n === 0) return [];
return buildTree(1, n);
};
//天使爆破组的记忆化递归
const generateTrees = (n) => {
if (n == 0) return [];
const memo = new Array(n + 1);
for (let i = 0; i < memo.length; i++) {
memo[i] = new Array(n + 1);
}
const getAllBSTs = (low, high) => {
if (low > high) return [null];
if (memo[low][high]) return memo[low][high];
if (low == high) return [new TreeNode(low)];
const res = [];
for (let i = low; i <= high; i++) {
const leftBSTs = getAllBSTs(low, i - 1);
const rightBSTs = getAllBSTs(i + 1, high);
for (const leftBST of leftBSTs) {
for (const rightBST of rightBSTs) {
const root = new TreeNode(i);
root.left = leftBST;
root.right = rightBST;
res.push(root);
}
}
}
return memo[low][high] = res;;
};
return getAllBSTs(1, n);
};
//动规https://leetcode-cn.com/problems/unique-binary-search-trees-ii/solution/si-lu-gen-bu-tong-shu-1chai-bu-duo-jiu-shi-xie-qi-/
var generateTrees = function(n) {
if(n == 0) return []
let DP = new Array(n+1)
DP[0] = [null]
DP[1] = [new TreeNode(1)]
if(n < 2) return DP[n]
for(let i = 2; i <= n; i++) {
DP[i] = []
for(let j = 0; j < i; j++) {
DP[j].forEach(ele => {
DP[i - j - 1].forEach(ele2 => {
DP[i].push(getNewBTS(ele,ele2,j))
})
})
}
}
return DP[n]
};
function getNewBTS(left, right, leftCount) {
let newNode = new TreeNode(leftCount + 1)
newNode.left = treeCopy(left)
newNode.right = traversalAddTree(newNode.val, treeCopy(right))
return newNode
}
function treeCopy(node) {
if(node == null) return null
let newNode = new TreeNode(node.val)
newNode.left = treeCopy(node.left)
newNode.right = treeCopy(node.right)
return newNode
}
function traversalAddTree(val, node) {
if(node == null) return null
node.val = node.val + val
traversalAddTree(val, node.left)
traversalAddTree(val, node.right)
return node
}