leetcode每日一題(2020-07-21):95. 不同的二叉搜尋樹 II
阿新 • • 發佈:2020-07-21
題目描述:
給定一個整數 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 }