/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
/**
* 此方法用于计算给定二叉树的最大深度
*
* @param root 二叉树的根节点
* @return 二叉树的最大深度值
*/
public int maxDepth(TreeNode root) {
// 如果根节点为空,说明树为空,返回深度 0
if (root == null) {
return 0;
} else {
// 递归计算左子树的深度
int leftHeight = maxDepth(root.left);
// 递归计算右子树的深度
int rightHeight = maxDepth(root.right);
// 取左子树和右子树深度中的最大值,并加上根节点这一层,得到整棵树的最大深度
return Math.max(leftHeight, rightHeight) + 1;
}
}
}
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
/**
* 判断两棵二叉树是否相同
*
* @param p 第一棵二叉树的根节点
* @param q 第二棵二叉树的根节点
* @return 如果两棵树相同返回 true,否则返回 false
*/
public boolean isSameTree(TreeNode p, TreeNode q) {
// 如果两棵树的根节点都为空,说明两棵树相同,返回 true
if (p == null && q == null) {
return true;
// 如果其中一棵树的根节点为空,另一棵不为空,说明两棵树不同,返回 false
} else if (p == null || q == null) {
return false;
// 如果两棵树的根节点值不同,说明两棵树不同,返回 false
} else if (p.val != q.val) {
return false;
} else {
// 递归判断两棵树的左子树和右子树是否相同,只有都相同,两棵树才相同
return isSameTree(p.left, q.left) && isSameTree(p.right, q.right);
}
}
}
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
/**
* 翻转二叉树的函数
* @param root 二叉树的根节点
* @return 翻转后的二叉树根节点
*/
public TreeNode invertTree(TreeNode root) {
// 如果根节点为空,直接返回空
if (root == null) {
return null;
}
// 递归翻转左子树,并将结果保存到 left 变量
TreeNode left = invertTree(root.left);
// 递归翻转右子树,并将结果保存到 right 变量
TreeNode right = invertTree(root.right);
// 将右子树设置为原来的左子树
root.right = left;
// 将左子树设置为原来的右子树
root.left = right;
// 返回翻转后的根节点
return root;
}
}
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
/**
* 判断给定的二叉树是否对称
*
* @param root 二叉树的根节点
* @return 如果二叉树对称返回 true,否则返回 false
*/
public boolean isSymmetric(TreeNode root) {
// 调用内部的 check 方法来进行对称性的检查,传入两个相同的根节点
return check(root, root);
}
/**
* 内部用于检查两棵子树是否对称的方法
*
* @param p 第一棵子树的根节点
* @param q 第二棵子树的根节点
* @return 如果两棵子树对称返回 true,否则返回 false
*/
private boolean check(TreeNode p, TreeNode q) {
// 如果两棵子树的根节点都为空,说明这部分对称,返回 true
if (p == null && q == null) {
return true;
}
// 如果其中一棵子树的根节点为空,另一棵不为空,说明不对称,返回 false
if (p == null || q == null) {
return false;
}
// 如果两棵子树根节点的值相等,并且左子树和右子树分别对称,返回 true
return p.val == q.val && check(p.left, q.right) && check(p.right, q.left);
}
}
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
private Map<Integer, Integer> indexMap; // 哈希表用于存储中序遍历中节点值与索引的对应关系
// 递归构建树的核心方法
public TreeNode myBuildTree(int[] preorder, int[] inorder, int preorder_left, int preorder_right, int inorder_left, int inorder_right) {
// 如果左边界大于右边界,说明没有节点可建,返回 null
if (preorder_left > preorder_right) {
return null;
}
// 前序遍历中的第一个节点就是根节点
int preorder_root = preorder_left;
// 在中序遍历中定位根节点的索引
int inorder_root = indexMap.get(preorder[preorder_root]);
// 根据根节点的值创建树节点
TreeNode root = new TreeNode(preorder[preorder_root]);
// 得到左子树中的节点数目
int size_left_subtree = inorder_root - inorder_left;
// 递归构造左子树,并连接到根节点
// 先序遍历中「从左边界+1开始的size_left_subtree个元素」对应中序遍历中「从左边界开始到根节点定位-1的元素」
root.left = myBuildTree(preorder, inorder, preorder_left + 1, preorder_left + size_left_subtree, inorder_left, inorder_root - 1);
// 递归构造右子树,并连接到根节点
// 先序遍历中「从左边界+1+左子树节点数目开始到右边界」的元素对应中序遍历中「从根节点定位+1到右边界的元素」
root.right = myBuildTree(preorder, inorder, preorder_left + size_left_subtree + 1, preorder_right, inorder_root + 1, inorder_right);
return root; // 返回构建的树节点
}
// 主方法,构建二叉树
public TreeNode buildTree(int[] preorder, int[] inorder) {
int n = preorder.length; // 获取节点总数
// 构造哈希映射,帮助快速定位根节点在中序遍历中的索引
indexMap = new HashMap<Integer, Integer>();
for (int i = 0; i < n; i++) {
indexMap.put(inorder[i], i); // 存储中序遍历中的节点值及其索引
}
// 调用递归方法构建树,初始边界为整个数组
return myBuildTree(preorder, inorder, 0, n - 1, 0, n - 1);
}
}
class Solution {
public TreeNode buildTree(int[] inorder, int[] postorder) {
// 调用深度优先搜索方法开始构建二叉树
return dfs(inorder, 0, inorder.length - 1, postorder, 0, postorder.length - 1);
}
private TreeNode dfs(int[] inorder, int inStart, int inEnd, int[] postorder, int postStart, int postEnd) {
// 如果中序遍历区间或后序遍历区间无效,返回 null,表示无法构建子树
if (inStart > inEnd || postStart > postEnd) {
return null;
}
// 从后序遍历数组的末尾获取当前子树的根节点值
int rootval = postorder[postEnd];
// 创建根节点
TreeNode root = new TreeNode(rootval);
// 在中序遍历数组中找到根节点的位置
int rootIndex = 0;
for (int i = inStart; i <= inEnd; i++) {
if (inorder[i] == rootval) {
rootIndex = i;
break;
}
}
// 计算左子树的节点数量
int leftSize = rootIndex - inStart;
// 递归构建左子树,左子树的中序遍历区间为 [inStart, rootIndex - 1],后序遍历区间为 [postStart, postStart + leftSize - 1]
root.left = dfs(inorder, inStart, rootIndex - 1, postorder, postStart, postStart + leftSize - 1);
// 递归构建右子树,右子树的中序遍历区间为 [rootIndex + 1, inEnd],后序遍历区间为 [postStart + leftSize, postEnd - 1]
root.right = dfs(inorder, rootIndex + 1, inEnd, postorder, postStart + leftSize, postEnd - 1);
// 返回构建好的当前子树的根节点
return root;
}
}
/*
// Definition for a Node.
class Node {
public int val;
public Node left;
public Node right;
public Node next;
public Node() {}
public Node(int _val) {
val = _val;
}
public Node(int _val, Node _left, Node _right, Node _next) {
val = _val;
left = _left;
right = _right;
next = _next;
}
};
*/
class Solution {
public Node connect(Node root) {
// 如果根节点为 null,则直接返回 null
if (root == null) {
return null;
}
Node head = root; // 当前层的头节点
// 循环遍历每一层,从上至下
while (head!= null) {
// 创建下一层的虚拟头节点
Node dummy = new Node(0);
Node temp = dummy; // 当前处理的节点
// 遍历当前层,连接下一层的节点
for (Node cur = head; cur!= null; cur = cur.next) {
// 如果当前节点有左子节点
if (cur.left!= null) {
temp.next = cur.left;
temp = temp.next; // 将 temp 移动到新连接的节点上
}
// 如果当前节点有右子节点
if (cur.right!= null) {
temp.next = cur.right;
temp = temp.next; // 将 temp 移动到新连接的节点上
}
}
// 移动到下一层的实际头节点处
head = dummy.next;
}
return root;
}
}
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
// 主方法:将二叉树扁平化为链表
public void flatten(TreeNode root) {
List<TreeNode> result = new ArrayList<>(); // 用于存储树节点的列表
helper(root, result); // 调用辅助方法填充节点列表
// 遍历结果列表,并重建链表的左右指针
for (int i = 0; i < result.size() - 1; i++) {
TreeNode pre = result.get(i); // 当前节点
TreeNode next = result.get(i + 1); // 下一个节点
pre.left = null; // 将当前节点的左指针设为 null
pre.right = next; // 将当前节点的右指针指向下一个节点
}
}
// 辅助方法:进行前序遍历并收集节点
public void helper(TreeNode root, List<TreeNode> result) {
if (root != null) { // 检查当前节点是否为空
result.add(root); // 将当前节点添加到结果列表中
helper(root.left, result); // 递归处理左子树
helper(root.right, result); // 递归处理右子树
}
}
}
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
/**
* 此方法用于判断二叉树中是否存在根节点到叶子节点的路径,使得路径上节点值的和等于给定的目标值
*
* @param root 二叉树的根节点
* @param sum 目标和
* @return 如果存在这样的路径返回 true,否则返回 false
*/
public boolean hasPathSum(TreeNode root, int targetSum) {
// 如果根节点为空,直接返回 false,因为不存在路径
if (root == null) {
return false;
}
// 如果当前节点是叶子节点(左右子节点都为空)
if (root.left == null && root.right == null) {
// 检查当前节点的值是否等于目标和
return root.val == targetSum;
}
// 递归地检查左子树中是否存在满足条件的路径
boolean left = hasPathSum(root.left, targetSum - root.val);
// 递归地检查右子树中是否存在满足条件的路径
boolean right = hasPathSum(root.right, targetSum - root.val);
// 如果左子树或右子树中存在满足条件的路径,返回 true
return left || right;
}
}
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public int sumNumbers(TreeNode root) {
// 调用深度优先搜索方法从根节点开始计算路径数字之和
return dfs(root, 0);
}
private int dfs(TreeNode root, int preSum) {
// 如果当前节点为 null,说明此分支无法形成有效路径,返回 0
if (root == null) {
return 0;
}
// 计算当前路径上的数字,即上一层传递下来的数字乘以 10 再加上当前节点的值
int sum = preSum * 10 + root.val;
// 如果当前节点是叶子节点,说明找到了一条完整的路径,直接返回当前路径上的数字
if (root.left == null && root.right == null) {
return sum;
}
// 如果当前节点不是叶子节点,继续递归遍历左子树和右子树,并将当前路径上的数字传递下去
return dfs(root.left, sum) + dfs(root.right, sum);
}
}
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class BSTIterator {
// 当前遍历到的节点
private TreeNode cur;
// 存储遍历路径上的节点的栈
private Deque<TreeNode> stack;
public BSTIterator(TreeNode root) {
// 初始化时将当前节点设为根节点
cur = root;
// 初始化栈
stack = new LinkedList<TreeNode>();
}
public int next() {
// 当当前节点不为 null 时,一直将左子节点入栈,直到找到最左节点
while (cur!= null) {
stack.push(cur);
cur = cur.left;
}
// 弹出栈顶节点,即为下一个最小的节点
cur = stack.pop();
int ret = cur.val;
// 将当前节点指向弹出节点的右子节点,继续下一轮遍历
cur = cur.right;
return ret;
}
public boolean hasNext() {
// 判断是否还有下一个节点,只要当前节点不为 null 或者栈不为空,就表示还有下一个节点
return cur!= null ||!stack.isEmpty();
}
}
/**
* Your BSTIterator object will be instantiated and called as such:
* BSTIterator obj = new BSTIterator(root);
* int param_1 = obj.next();
* boolean param_2 = obj.hasNext();
*/
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
/**
* 该方法用于计算给定二叉树中的节点总数
*
* @param root 二叉树的根节点
* @return 二叉树的节点总数
*/
public int countNodes(TreeNode root) {
// 如果根节点为空,返回 0,表示没有节点
if (root == null) {
return 0;
}
// 递归计算左子树的节点数
int leftCount = countNodes(root.left);
// 递归计算右子树的节点数
int rightCount = countNodes(root.right);
// 加上当前根节点 1,返回总的节点数
return leftCount + rightCount + 1;
}
}
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
// 存储最近公共祖先节点
private TreeNode ans;
private boolean dfs(TreeNode root, TreeNode p, TreeNode q) {
// 如果当前节点为 null,则返回 false,表示未找到 p 和 q
if (root == null) return false;
// 递归遍历左子树,看左子树中是否有 p 和 q
boolean lson = dfs(root.left, p, q);
// 递归遍历右子树,看右子树中是否有 p 和 q
boolean rson = dfs(root.right, p, q);
// 如果左子树和右子树都有 p 和 q,或者当前节点的值等于 p 或 q 的值,并且左子树或右子树中有 p 和 q,那么当前节点就是最近公共祖先
if ((lson && rson) || ((root.val == p.val || root.val == q.val) && (lson || rson))) {
ans = root;
}
// 返回当前子树中是否有 p 和 q,即左子树中有或者右子树中有或者当前节点等于 p 或 q
return lson || rson || (root.val == p.val || root.val == q.val);
}
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
// 调用深度优先搜索方法来查找最近公共祖先
this.dfs(root, p, q);
// 返回找到的最近公共祖先节点
return this.ans;
}
}