feat: 添加二叉搜索树98,230,530,1382
This commit is contained in:
parent
f53e76dcf0
commit
21d1a55888
@ -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);
|
||||
}
|
@ -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:
|
@ -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;
|
||||
}
|
||||
|
||||
/*
|
||||
使用迭代实现中序遍历
|
||||
*/
|
70
top-interview-leetcode150/binary-search-tree/98验证二叉搜索树.js
Normal file
70
top-interview-leetcode150/binary-search-tree/98验证二叉搜索树.js
Normal file
@ -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;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user