654.最大二叉树 🌟🌟
力扣链接 🌟🌟
题目描述
给定一个不含重复元素的整数数组。一个以此数组构建的最大二叉树定义如下:
- 二叉树的根是数组中的最大元素。
- 左子树是通过数组中最大值左边部分构造出的最大二叉树。
- 右子树是通过数组中最大值右边部分构造出的最大二叉树。
通过给定的数组构建最大二叉树,并且输出这个树的根节点。
示例 :
输入:[3, 2, 1, 6, 0, 5]
// 输出 树根节点
// 6
// / \
// 3 5
// \ /
// 2 0
// \
// 1
解题思路
- 关键:构造二叉树一定是前序遍历,先有根节点,递归构造左右子树
递归三部曲:
明确递归函数的参数和返回值
- 参数 1:传入的数组
- 返回值:根节点
明确终止条件
- 数组长度为 1 时,就是叶子节点,直接构造叶子节点并返回
确定单层递归逻辑
找最大值和对应下标,值用来构造根节点,下标用来分割数组(左右子树)
let max = nums[0] let maxIndex = 0 for (let i = 1; i < nums.length; i++) { if (nums[i] > max) { max = nums[i] maxIndex = i } } const root = new TreeNode(max)
分割数组
用左区间构造左子树
root.left = constructMaximumBinaryTree(nums.slice(0, maxIndex))
用右区间构造右子树
root.right = constructMaximumBinaryTree(nums.slice(maxIndex + 1))
function constructMaximumBinaryTree(nums) {
if (!nums.length) return null
const max = num[0]
const maxIndex = 0
for (let i = i; i < nums.length; i++) {
if (nums[i] > max) {
max = nums[i]
maxIndex = i
}
}
const root = new TreeNode(max)
root.left = constructMaximumBinaryTree(nums.slice(0, maxIndex))
root.right = constructMaximumBinaryTree(nums.slice(maxIndex + 1))
return root
}
617.合并二叉树 🌟
力扣链接 🌟
题目描述
给定两个二叉树,想象当你将它们中的一个覆盖到另一个上时,两个二叉树的一些节点便会重叠。
你需要将他们合并为一个新的二叉树。合并的规则是如果两个节点重叠,那么将他们的值相加作为节点合并后的新值,否则不为 NULL 的节点将直接作为新二叉树的节点。
示例:
// Tree 1 Tree 2
// 1 2
// / \ / \
// 3 2 1 3
// / \ \
// 5 4 7
// 合并后
// 3
// / \
// 4 5
// /\ \
// 5 4 7
解题思路
采用前序遍历最直观,与遍历一个树的逻辑一样
递归
递归三部曲:
确定递归函数的参数和返回值
- 参数 1:Tree 1
- 参数 2:Tree 2
- 返回值:新二叉树的 root
确定终止条件
遍历同一个节点时,Tree 1 为空,返回 Tree 2;Tree 2 为空,返回 Tree 1
if (!root1) return root2 if (!root2) return root1
确定单层递归逻辑
- 将两个树节点值相加
root.val += root2.val
- 递归处理左子树
- 递归处理右子树
- 将两个树节点值相加
function mergeTrees(root1, root2) {
if (!root1) return root2
if (!root2) return root1
root1.val += root2.val
root1.left = mergeTrees(root1.left, root2.left)
root1.right = mergeTrees(root1.right, root2.right)
return root1
}
迭代
步骤:
- 初始化队列:root1 和 root2 进入队列
- 遍历队列:弹出 root1 和 root2,累加
root1.val += root2.val
- 压入左子节点:同时压入 root1.left 和 root2.left,都不为 null 时
- 压入右子节点:同时压入 root1.right 和 root2.right,都不为 null 时
- 注意:如果 root1.left 或 root1.right 为 null 时,直接将 root2.left 或 root2.right 替换为 root1.left 或 root1.right
function mergeTrees(root1, root2) {
if (!root1) return root2
if (!root2) return root1
const queue = [root1, root2]
while (queue.length) {
const node1 = queue.shift()
const node2 = queue.shift()
node1.val += node2.val
if (node1.left && node2.left) {
queue.push(node1.left)
queue.push(node2.left)
}
if (node1.right && node2.right) {
queue.push(node1.right)
queue.push(node2.right)
}
if (!node1.left && node2.left) {
node1.left = node2.left
}
if (!node1.right && node2.right) {
node1.right = node2.right
}
}
return root1
}
700.二叉搜索树中的搜索 🌟
力扣链接 🌟
题目描述
给定二叉搜索树(BST)的根节点和一个值。 你需要在 BST 中找到节点值等于给定值的节点。 返回以该节点为根的子树。 如果节点不存在,则返回 NULL。
示例:
// 给定二叉搜索树:
// 4
// / \
// 2 7
// / \
// 1 3
// 和值:2
// 返回
// 2
// / \
// 1 3
解题思路
二叉搜索树:根节点比左子树所有节点的值都大、比右子树所有节点的值都小,同时左右子树都是二叉搜索树
递归
递归三部曲:
确定递归函数的参数和返回值
- 参数 1:根节点
- 参数 2:要搜索的值
- 返回值:搜索的值所在的节点
确定终止条件
如果 root 为 null 或者找到数值了,返回 root
if (!root || node.val === val) return root
确定单层递归逻辑
这里与普通二叉树的递归不同
- 若目标值小于当前节点值,递归搜索左子树
- 若目标值大于当前节点值,递归搜索右子树
function searchBST(root, val) {
if (!root || root.val === val) return root
if (root.val > val) {
return searchBST(root.left, val)
}
if (root.val < val) {
return searchBST(root.right, val)
}
}
迭代
- 使用循环代替递归,从根节点开始遍历
- 根据当前节点值与目标值的比较结果,移动到左子节点或右子节点
- 找到匹配的节点时立即返回,否则遍历结束返回 null
function searchBST(root, val) {
while (root) {
if (root.val === val) return root
if (root.val > val) {
root = root.left
}
if (root.val < val) {
root = root.right
}
}
return root
}
98.验证二叉搜索树 🌟🌟
力扣链接 🌟🌟
题目描述
给定一个二叉树,判断其是否是一个有效的二叉搜索树。
假设一个二叉搜索树具有如下特征:
- 节点的左子树只包含小于当前节点的数。
- 节点的右子树只包含大于当前节点的数。
- 所有左子树和右子树自身必须也是二叉搜索树。
// 2
// / \
// 1 3
// 输出 true
解题思路
常见错误:只比较每个节点与其左右节点的关系,没有考虑全局上节点的关系,如:某个右子树的左节点可能比父节点小,同时比根节点小
需要一个区间[min, max]来确定当前节点值是否在这个区间
递归
三部曲
确定递归函数的参数和返回值
- 参数 1:根节点
- 参数 2:最小值,从根节点开始为-Infinity,右子树需要不断更新最小值为当前值
- 参数 3:最大值,从节点为最大值,左子树需要不断更新最大值为当前值
- 返回值:根节点
确定终止条件
- 根节点为 null 时,返回 true
- 当前值不在[min, max]区间时,返回 false
确定单层递归逻辑
- 递归左右子树
代码
function isValidBST(root) {
const traverse = (root, min, max) => {
if (!root) return true
if (root.val <= min || root.val >= max) return false
return (
traverse(root.left, min, root.val) && traverse(root.right, root.val, max)
)
}
return traverse(root, -Infinity, Infinity)
}
迭代
思路:
- 使用栈存储节点及其允许的上下界
- 遍历时检查节点值是否在范围内,并更新子节点的范围
function isValidBST(root) {
if (!root) return true
const stack = [[root, -Infinity, Infinity]]
while (stack.length) {
const [node, min, max] = stack.pop()
if (node.val <= min || node.val >= max) return false
node.left && stack.push([node.left, min, node.val])
node.right && stack.push([node.right, node.val, max])
}
return true
}
京ICP备2022027737号
Copyright © 2022 - present @wangxiang