diff --git a/top-interview-leetcode150/binary-search-tree/1382将二叉搜索树变平衡.js b/top-interview-leetcode150/binary-search-tree/1382将二叉搜索树变平衡.js new file mode 100644 index 0000000..e2c4efa --- /dev/null +++ b/top-interview-leetcode150/binary-search-tree/1382将二叉搜索树变平衡.js @@ -0,0 +1,65 @@ +/** + * 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 {TreeNode} root + * @return {TreeNode} + */ +const balanceBST = function (root) { + +}; + +/* +现在不来考虑二叉搜索树变平衡,考虑一下给你一个有序的数组你如何将他变平衡,我的猜想是这样的,直接寻找找到数组序列的中间位置mid =Math.floor(left + right) +将mid作为这个根节点,将mid左侧的元素(不是小于等于)全部用来构建左子树,将mid右侧的元素全部用来构建右子树,之后在子树上重复这个过程,最后构建出来的树, +就是一棵平衡二叉搜索树,原因很简单,log2(k),和log2(k+1)的差不会超过1,一个区间被分割无外乎两种情况,左边和右边的数量相等,或者左边和右边的数量相差 +1,这是满足平衡二叉树定义的,所以这种构建的贪心策略是合理的。 +记住:一个有序的序列只要取中间值作为根节点,左右侧序列作为左右子树,之后递归处理左右子树,最终就能构建一颗平衡二叉搜索树,而二叉搜索树的中序遍历恰好 +是有序序列,所以只需要将二叉搜索树遍历,之后拿到遍历的结果重新按照上面的方法构建一颗平衡二叉搜索(BST)树就行 +*/ +function TreeNode(val, left, right) { + this.val = (val === undefined ? 0 : val); + this.left = (left === undefined ? null : left); + this.right = (right === undefined ? null : right); +} + +function f1(root) { + // 1.遍历二叉搜索树(BST)获取对应有序序列 + const inorder = []; + const inorderTraversal = (root) => { + if (!root) return; + // 遍历左子树 + inorderTraversal(root.left); + // 将中序遍历的值存入数组 + inorder.push(root.val); + // 遍历右子树 + inorderTraversal(root.right); + }; + + inorderTraversal(root); // 对原始树进行中序遍历 + + // 2.递归构建平衡二叉搜索树 + const sortedArrayToBST = (left, right) => { + if (left > right) return null; // 当前区间不存在元素,无法构建子树 + + const mid = Math.floor((left + right) / 2); + // 为当前区间所有元素构建根节点 + const curRoot = new TreeNode(inorder[mid]); + // 递归构建左子树 + const leftNode = sortedArrayToBST(left, mid - 1); + // 递归构建右子树 + const rightNode = sortedArrayToBST(mid + 1, right); + // 连接左右子树 + curRoot.left = leftNode; + curRoot.right = rightNode; + return curRoot; + }; + + return sortedArrayToBST(0, inorder.length - 1); +} diff --git a/top-interview-leetcode150/binary-search-tree/230二叉搜索树中第 K 小的元素.js b/top-interview-leetcode150/binary-search-tree/230二叉搜索树中第 K 小的元素.js new file mode 100644 index 0000000..a6d9eca --- /dev/null +++ b/top-interview-leetcode150/binary-search-tree/230二叉搜索树中第 K 小的元素.js @@ -0,0 +1,52 @@ +/** + * 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 {TreeNode} root + * @param {number} k + * @return {number} + */ +const kthSmallest = function (root, k) { + +}; + +/* +根据二叉搜索树的特性,直接对其进行中序遍历,遍历到的第k个数就是第k小,这里使用迭代的方式,好返回结果 +*/ +function f1(root, k) { + const stack = []; // 栈用于模拟中序遍历 + let node = root; // 从根节点开始遍历 + + while (node || stack.length > 0) { + // 先处理左子树,将所有左子树节点压入栈中 + while (node) { + stack.push(node); + node = node.left; + } + + // 弹出栈顶元素并访问 + node = stack.pop(); + + // 递减k,如果k为0,说明我们已经找到了第k个最小值 + if (--k === 0) { + return node.val; + } + + // 处理右子树 + node = node.right; + } + + return null; // 如果没有找到k个元素,返回null(一般不会发生) +} + +/* +当一如果当前节点就是目标节点,那么它的左子树的数量一定是k-1个,如果左子树的数量小于k-1个那么目标节点一定存在右子树中, +以当前节点右子树为根节点继续寻找此时k要出去左子树的left加上自己一共left + 1个,所以以右子节点为更节点的子树只需寻找 +第 k-(left+1)个大的数。使用面向对象的写法封装。 +*/ +// TODO: diff --git a/top-interview-leetcode150/binary-search-tree/530二叉搜索树的最小差的绝对值.js b/top-interview-leetcode150/binary-search-tree/530二叉搜索树的最小差的绝对值.js new file mode 100644 index 0000000..6a7cc29 --- /dev/null +++ b/top-interview-leetcode150/binary-search-tree/530二叉搜索树的最小差的绝对值.js @@ -0,0 +1,52 @@ +/** + * 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 {TreeNode} root + * @return {number} + */ +const getMinimumDifference = function (root) { + +}; + +/* +二叉搜索树的一个重要特征就是,中序遍历的结果是一个升序序列,所以只要中序遍历整个二叉树,前一个节点和当前节点作比较的值的绝对值就可能 +是这个最小的差值 +*/ +function f1(root) { + let prev = null; // 记录前一个节点的值 + let minDiff = Infinity; // 初始化最小差值为正无穷 + + // 中序遍历函数 + function inOrder(node) { + if (!node) return; + + // 先遍历左子树 + inOrder(node.left); + + // 当前节点与前一个节点的差值 + if (prev !== null) { + minDiff = Math.min(minDiff, Math.abs(node.val - prev)); + } + + // 更新前一个节点为当前节点 + prev = node.val; + + // 再遍历右子树 + inOrder(node.right); + } + + // 从根节点开始中序遍历 + inOrder(root); + + return minDiff; +} + +/* +使用迭代实现中序遍历 +*/ diff --git a/top-interview-leetcode150/binary-search-tree/98验证二叉搜索树.js b/top-interview-leetcode150/binary-search-tree/98验证二叉搜索树.js new file mode 100644 index 0000000..71c79b7 --- /dev/null +++ b/top-interview-leetcode150/binary-search-tree/98验证二叉搜索树.js @@ -0,0 +1,70 @@ +/** + * 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 {TreeNode} root + * @return {boolean} + */ +const isValidBST = function (root) { + +}; + +/* +思路:根据二叉搜索树的定义,BST的中序遍历是一个严格的递增序列,所以只要一次遍历,判断后一个树是否是严格大于当前的树,如果小于等于, +那么这个二叉树不是搜索二叉树 +*/ + +function f1(root) { + let prev = null; // 前一个节点的值 + + const inordertraversal = (node) => { + if (!node) return true; // 空节点被视为有效BST + // 遍历左子树如果左子树不是BST立即返回false + if (!inordertraversal(node.left)) return false; + // 处理当前节点 + if (prev !== null && prev >= node.val) return false; + // 更新prev为当前节点值 + prev = node.val; + // 遍历右子树 + return inordertraversal(node.right); + }; + + return inordertraversal(root); +} + +/* +使用迭代法中序遍历,返回更直接 +*/ +function f2(root) { + const stack = []; + let prev = null; + + // 迭代法中序遍历 + while (stack.length > 0 || root !== null) { + // 遍历左子树,直到最左叶子节点 + while (root !== null) { + stack.push(root); + root = root.left; + } + + // 访问当前节点 + root = stack.pop(); + + // 当前节点值必须大于前一个节点值 + if (prev !== null && root.val <= prev) { + return false; // 发现不符合要求,返回false + } + + // 更新prev为当前节点值 + prev = root.val; + + // 访问右子树 + root = root.right; + } + return true; +}