简介
题目01: 查询二叉树内最左侧最底部节点 (LeetCode 513)
题目02: 查询二叉树的路径总和 (LeetCode 112)
题目03: 构造最大二叉树 (LeetCode 654)
题目04: 合并二叉树 (LeetCode 617)
题目05: 二叉搜索树搜索 (LeetCode 700 )
题目 01 - 查询二叉树左下角的值
原题链接
题目描述
给定一个二叉树的 根节点 root,请找出该二叉树的 最底层 最左边 节点的值。 假设二叉树中至少有一个节点。
如果仅有根节点: 返回根节点的值
思路
方法
- 层序遍历;借助队列结构
- 修改入队顺序:如果右子节点不为空,右子节点先入队,再将左子节点入队
- 出队顺序: 右子节点先出队,之后左子节点
- 因此,每一层树层的最左侧节点为队列内的对尾节点
代码实现
class Solution {
public int findBottomLeftValue(TreeNode root) {
// 检查输入
if (root == null) {
return 0;
}
// 队列,辅助遍历各个树层内的节点
Deque<TreeNode> queue = new LinkedList<>();
queue.offer(root);
/*
遍历每一树层
入队顺序: 右 -> 左; 出队顺序: 右 -> 左;最左侧元素最后出队
*/
int bottomLeft = 0;
while (!queue.isEmpty()) {
int size = queue.size();
while (size-- > 0) {
TreeNode top = queue.pop();
// 更新,每一层对尾元素为当前层的最左元素
bottomLeft = top.val;
// 右子节点先入队
if (top.right != null) {
queue.offer(top.right);
}
// 左子节点先入队
if (top.left != null) {
queue.offer(top.left);
}
}
}
return bottomLeft;
}
}
执行结果
- 时间复杂度:
O(N) - 空间复杂度:
O(N)
题目 02 - 求二叉树的路径总和
原题链接
题目描述
给你二叉树的根节点
root和一个表示目标和的整数targetSum。判断该树中是否存在
根节点到叶子节点的路径,这条路径上所有节点值相加等于目标和targetSum。如果存在,返回
true;否则,返回false叶子节点 是指没有子节点的节点。
思路
方法
- 递归 递归返回条件:
- 如果当前路径之和等于 targetSum, 且已经抵达叶子节点,返回true
- 当前节点为空返回 false
- 单层遍历条件:
- 如果左子节点不为空:
- 更新之前记录当前 currVal = sum;
- 更新 sum + node.left.val
- 返回当前层后 sum = currVal
- 如果右子节点不为空,同理
代码实现
class Solution {
public boolean hasPathSum(TreeNode root, int targetSum) {
//检查输入
if (root == null) {
return false;
}
if(root.left == null && root.right == null) {
return root.val == targetSum;
}
return isPathExist(root, root.val, targetSum);
}
public boolean isPathExist(TreeNode node, int sum, int targetSum) {
if (node == null) {
return false;
}
// 如果和满足并且抵达一个叶子节点
if (sum == targetSum && node.left == null && node.right == null) {
return true;
}
// 左子节点不为空
boolean isLeftExist = false;
if (node.left != null) {
// 更新路径之和
isLeftExist = isPathExist(node.left, sum + node.left.val, targetSum);
}
// 右子节点不为空
boolean isRightExist = false;
if (node.right != null) {
// 更新路径之和
isRightExist = isPathExist(node.right, sum + node.right.val, targetSum);
}
return isLeftExist || isRightExist;
}
}
执行结果
- 时间复杂度:
O(N) - 空间复杂度:
O(H)
题目 03 - 最大二叉树
原题链接
题目描述
给定一个不重复的整数数组
nums。 最大二叉树 可以用下面的算法从nums递归地构建:
- 创建一个根节点,其值为 nums 中的最大值。
- 递归地在最大值 左边 的 子数组前缀上 构建左子树。
- 递归地在最大值 右边 的 子数组后缀上 构建右子树。
- 返回 nums 构建的 最大二叉树 。
思路
方法
- 递归
- 借助左右指针
left right遍历数组: - 每层递归内
- 遍历区间
[left, right]获取最大节点值所在的下标 maxIdx - 基于最大值所在的下标划分当前左半区为
[left, maxIdx]右半区为[maxIdx + 1, right] - 递归返回条件:
- a.
left < right, 无节点值可用;返回空 - b.
left = right; 叶子节点值;构造一个节点返回
- 设当前层内父节点为
node,node.left通过左半区[left, maxIdx]得到;node.right通过右半区得到[maxIdx + 1, rightIdx]
代码实现
class Solution {
public boolean hasPathSum(TreeNode root, int targetSum) {
//检查输入
if (root == null) {
return false;
}
if(root.left == null && root.right == null) {
return root.val == targetSum;
}
return isPathExist(root, root.val, targetSum);
}
public boolean isPathExist(TreeNode node, int sum, int targetSum) {
if (node == null) {
return false;
}
// 如果和满足并且抵达一个叶子节点
if (sum == targetSum && node.left == null && node.right == null) {
return true;
}
// 左子节点不为空
boolean isLeftExist = false;
if (node.left != null) {
// 更新路径之和
isLeftExist = isPathExist(node.left, sum + node.left.val, targetSum);
}
// 右子节点不为空
boolean isRightExist = false;
if (node.right != null) {
// 更新路径之和
isRightExist = isPathExist(node.right, sum + node.right.val, targetSum);
}
return isLeftExist || isRightExist;
}
}
执行结果
- 时间复杂度:
O(N) - 空间复杂度:
O(H)
题目 04 - 合并二叉树
原题链接
题目描述
给你两棵二叉树: root1 和 root2 。
想象一下,当你将其中一棵覆盖到另一棵之上时,两棵树上的一些节点将会重叠(而另一些不会)。
你需要将这两棵树合并成一棵新二叉树。合并的规则是:如果两个节点重叠,那么将这两个节点的值相加作为合并后节点的新值;
否则,不为 null 的节点将直接作为新二叉树的节点。 返回合并后的二叉树。 注意: 合并过程必须从两个树的根节点开始。
思路
方法
- 递归
- 递归返回条件: 节点为空
- 如果 node1 左子树为空而 node2 左子树不为空; 将其加入到node1作为左子节点
- 如果 node1 右子树为空而 node2 右子树不为空; 将其加入到node1作为左子节点
- 如果 node1 和 node2 当前都不为空,累加值 node1.val += node2.val
代码实现
class Solution {
public TreeNode mergeTrees(TreeNode root1, TreeNode root2) {
//递归返回条件一: 都为空
if(root1 == null && root2 == null) {
return null;
}
//返回条件二, 其中一个子树为空,返回另一个
if(root1 == null && root2 != null) {
return root2;
}
if(root1 != null && root2 == null) {
return root1;
}
//以 root1 树为基树,将root2合并至root1
root1.val += root2.val; //合并,累加值
root1.left = mergeTrees(root1.left, root2.left); //合并左子树
root1.right = mergeTrees(root1.right, root2.right); //合并右子树
return root1;
}
}
代码简化
class Solution {
public TreeNode mergeTrees(TreeNode root1, TreeNode root2) {
//递归返回条件
if(root2 == null) return root1;
if(root1 == null) return root2;
//两个结点值相加
root1.val += root2.val;
//将 root2 合并到 root1 树
root1.left = mergeTrees(root1.left, root2.left);
root1.right = mergeTrees(root1.right, root2.right);
return root1;
}
}
执行结果
- 时间复杂度:
O(N) - 空间复杂度:
O(H)
题目 05 - 二叉搜索树搜索
原题链接
题目描述
给定二叉搜索树(BST)的根节点 root 和一个整数值 val。
你需要在 BST 中找到节点值等于 val 的节点。 返回以该节点为根的子树。 如果节点不存在,则返回 null 。
思路
方法
- 递归
- 由于二叉搜索树,如果当前父节点值比 val 小,递归查找左子树
- 否则,递归查找右子树
- 直到 node.val == val
代码实现
class Solution {
public TreeNode searchBST(TreeNode root, int val) {
//递归返回条件,为空或者找到匹配的子树根节点
if(root == null || root.val == val) {
return root;
}
//比val小,递归查找左子树
if(root.val < val) {
return searchBST(root.right, val);
}
//比val大,递归查找右子树
if(root.val > val) {
return searchBST(root.left, val);
}
//无则返回null
return null;
}
}
执行结果
- 时间复杂度:
O(logN) - 空间复杂度:
O(H)