当前位置: 首页 > news >正文

面试 TOP101 二叉树专题题解汇总Java版(BM23 —— BM41)

二叉树

题号题目名称核心思路时间复杂度空间复杂度代码亮点牛客原题链接
BM23二叉树的前序遍历递归实现,先访问根节点,再递归遍历左子树,最后递归遍历右子树O(n)O(n)使用辅助函数 preorder,逻辑清晰,递归终止条件明确🔗 直达
BM24二叉树的中序遍历递归实现,先递归遍历左子树,访问根节点,再递归遍历右子树O(n)O(n)递归逻辑简洁,通过辅助函数 inorder 实现🔗 直达
BM25二叉树的后序遍历递归实现,先递归遍历左子树,再递归遍历右子树,最后访问根节点O(n)O(n)递归逻辑清晰,辅助函数 postorder 实现后序遍历🔗 直达
BM26求二叉树的层序遍历使用队列实现广度优先搜索,逐层访问节点O(n)O(n)使用队列存储待访问的节点,逐层处理🔗 直达
BM27按之字形顺序打印二叉树层序遍历结合反转操作,偶数层反转当前层的节点值O(n)O(n)使用队列实现层序遍历,通过 Collections.reverse 反转偶数层🔗 直达
BM28二叉树的最大深度使用队列实现广度优先搜索,逐层访问节点,计算最大深度O(n)O(n)使用队列存储待访问的节点,逐层处理,每层深度加1🔗 直达
BM29二叉树中和为某一值的路径(一)递归或广度优先搜索,记录从根节点到叶子节点的路径和O(n)O(n)递归方法简洁,广度优先搜索使用 Pair 类记录路径和🔗 直达
BM30二叉搜索树与双向链表递归或非递归中序遍历,将二叉搜索树转换为双向链表O(n)O(n)递归方法中使用全局变量 headpre,非递归方法使用栈🔗 直达
BM31对称的二叉树递归或层序遍历,判断二叉树是否对称O(n)O(n)递归方法中使用辅助函数 chk,层序遍历使用队列🔗 直达
BM32合并二叉树递归合并两棵二叉树,对应节点值相加O(n)O(n)递归方法简洁,新建节点 head 作为合并后的根节点🔗 直达
BM33二叉树的镜像递归或栈实现,交换每个节点的左右子树O(n)O(n)递归方法简洁,栈方法使用迭代🔗 直达
BM34判断是不是二叉搜索树递归或中序遍历,判断中序遍历结果是否递增O(n)O(n)递归方法中使用全局变量 pre,中序遍历方法使用栈🔗 直达
BM35判断是不是完全二叉树使用队列实现层序遍历,检查是否为完全二叉树O(n)O(n)使用队列存储待访问的节点,逐层处理🔗 直达
BM36判断是不是平衡二叉树递归计算子树高度,判断是否平衡O(n)O(n)使用辅助函数 depth,递归计算子树高度🔗 直达
BM37二叉搜索树的最近公共祖先递归或路径比较,找到最近公共祖先O(n)O(n)使用辅助函数 getPath,记录路径🔗 直达
BM38在二叉树中找到两个节点的最近公共祖先递归或路径比较,找到最近公共祖先O(n)O(n)使用辅助函数 lowestCommonAncestor,递归查找🔗 直达
BM39序列化二叉树递归或层序遍历,序列化二叉树O(n)O(n)使用辅助函数 SerializeFuctionDeserializeFuction🔗 直达
BM40重建二叉树递归或栈遍历,根据前序和中序遍历重建二叉树O(n)O(n)使用辅助函数 buildTree,递归重建🔗 直达
BM41输出二叉树的右视图递归或层序遍历,输出二叉树的右视图O(n)O(n)使用辅助函数 rightSideView,层序遍历🔗 直达

✅ 建议复习顺序(由易到难):

BM23 → BM24 → BM25 → BM26 → BM27 → BM29 → BM30 → BM31 → BM32 → BM33 → BM34 → BM35 → BM36 → BM37 → BM38 → BM39 → BM40 → BM41

BM23 二叉树的前序遍历

二叉树的前序遍历_牛客题霸_牛客网
https://www.nowcoder.com/practice/5e2135f4d2b14eb8a5b06fab4c938635?tpId=295&tags=&title=&difficulty=0&judgeStatus=0&rp=0&sourceUrl=%2Fexam%2Foj

import java.util.*;public class Solution {void preorder(List<Integer> list, TreeNode root){ // 1. 定义前序遍历辅助方法if(root == null) return ; // 2. 如果当前节点为空,直接返回list.add(root.val); // 3. 访问当前节点,将值加入列表preorder(list,root.left); // 4. 递归遍历左子树preorder(list,root.right); // 5. 递归遍历右子树}public int[] preorderTraversal (TreeNode root) {List<Integer> list = new ArrayList(); // 6. 创建一个列表用于存储遍历结果preorder(list,root); // 7. 调用前序遍历辅助方法int [] res = new int [list.size()]; // 8. 创建一个数组用于存储最终结果for(int i = 0 ; i < list.size(); i ++) res[i] = list.get(i); // 9. 将列表中的值复制到数组return res; // 10. 返回结果数组}
}

BM24 二叉树的中序遍历

二叉树的中序遍历_牛客题霸_牛客网
https://www.nowcoder.com/practice/0bf071c135e64ee2a027783b80bf781d?tpId=295&tags=&title=&difficulty=0&judgeStatus=0&rp=0&sourceUrl=%2Fexam%2Foj


import java.util.*;public class Solution {void inorder(ArrayList<Integer> list, TreeNode root){ // 1. 定义中序遍历辅助方法if(root == null) return; // 2. 如果当前节点为空,直接返回inorder(list,root.left); // 3. 递归遍历左子树list.add(root.val); // 4. 访问当前节点,将值加入列表inorder(list,root.right); // 5. 递归遍历右子树}public int[] inorderTraversal (TreeNode root) {ArrayList<Integer> list = new ArrayList<>(); // 6. 创建一个列表用于存储遍历结果inorder(list,root); // 7. 调用中序遍历辅助方法int [] res = new int [list.size()]; // 8. 创建一个数组用于存储最终结果for(int i = 0 ; i < list.size() ; i ++){ // 9. 将列表中的值复制到数组res[i] = list.get(i);}return res; // 10. 返回结果数组}
}

BM25 二叉树的后序遍历

二叉树的后序遍历_牛客题霸_牛客网
https://www.nowcoder.com/practice/1291064f4d5d4bdeaefbf0dd47d78541?tpId=295&tags=&title=&difficulty=0&judgeStatus=0&rp=0&sourceUrl=%2Fexam%2Foj%3FquestionJobId%3D10%26subTabName%3Donline_coding_page

import java.util.*;public class Solution {// 1. 递归辅助函数:后序遍历子树并把节点值追加到 listvoid postorder(ArrayList<Integer> list, TreeNode root){if(root == null) return;          // 2. 空节点直接返回postorder(list,root.left);        // 3. 递归遍历左子树postorder(list,root.right);       // 4. 递归遍历右子树list.add(root.val);               // 5. 访问当前节点:将值加入 list}// 6. 主函数:返回整棵树的后序遍历结果(int 数组形式)public int[] postorderTraversal (TreeNode root) {ArrayList<Integer> list = new ArrayList<Integer>(); // 7. 用于存放遍历结果的动态数组postorder(list,root);            // 8. 调用辅助函数完成后序遍历并填充 listint [] res = new int[list.size()]; // 9. 创建与 list 长度相同的 int 数组for(int i = 0 ; i < list.size() ; i ++) res[i] = list.get(i);        // 10. 将 list 中的值逐个复制到数组 resreturn res;                      // 11. 返回后序遍历结果数组}
}

BM26 求二叉树的层序遍历

求二叉树的层序遍历_牛客题霸_牛客网
https://www.nowcoder.com/practice/04a5560e43e24e9db4595865dc9c63a3?tpId=295&tags=&title=&difficulty=0&judgeStatus=0&rp=0&sourceUrl=%2Fexam%2Foj%3FquestionJobId%3D10%26subTabName%3Donline_coding_page

import java.util.*;public class Solution {public ArrayList<ArrayList<Integer>> levelOrder (TreeNode root) {ArrayList<ArrayList<Integer>> res = new ArrayList();// 1. 创建数据来存放答案if(root == null) return res;// 2. 如果是空树 则返回空Queue<TreeNode> q = new ArrayDeque<TreeNode> ();// 3. 创建一个双端队列来遍历q.add(root);// 4. 初始化根节点放到队列之中while(!q.isEmpty()){// 5. 如果队列不是空的ArrayList<Integer> row = new ArrayList();// 6. 存放当前层的节点的值int n = q.size();// 7. 计算当前层有多少个节点for(int i = 0 ; i < n ; i ++){// 8. 处理当前的所有节点TreeNode cur = q.poll();// 9. 结点出队row.add(cur.val);// 10. 当前节点的答案if(cur.left != null) q.add(cur.left);// 11. 当前层节点的左节点入队(若有)if(cur.right != null) q.add(cur.right);// 12. 当前层节点的右节点入队(若有)}res.add(row);// 13. 添加答案}return res;}
}

BM27 按之字形顺序打印二叉树

按之字形顺序打印二叉树_牛客题霸_牛客网
https://www.nowcoder.com/practice/91b69814117f4e8097390d107d2efbe0?tpId=295&tqId=644&sourceUrl=%2Fexam%2Foj%3FquestionJobId%3D10%26subTabName%3Donline_coding_page

  1. 直接利用队列 广搜
import java.util.*;public class Solution {public ArrayList<ArrayList<Integer>> Print (TreeNode pRoot) {TreeNode h = pRoot;                          // 1. 用临时变量 h 保存根节点引用,避免直接修改形参ArrayList<ArrayList<Integer>> res = new ArrayList<ArrayList<Integer>>(); // 2. 创建最终结果列表 res,用于存放按层划分的节点值if(h == null) return res;                    // 3. 如果根节点为空,直接返回空的结果列表Queue<TreeNode> q = new LinkedList<TreeNode>(); // 4. 创建队列 q,用于实现广度优先(层序)遍历q.offer(h);                                  // 5. 将根节点加入队列,作为遍历起点int f = 0;                                   // 6. 初始化层号计数器 f 为 0(根节点视为第 0 层)while(!q.isEmpty()){                         // 7. 只要队列中还有节点,就继续循环ArrayList<Integer> row = new ArrayList<>(); // 8. 创建当前层的节点值列表 rowint n = q.size();                        // 9. 获取当前层的节点数量 n(队列长度)for(int i = 0 ; i < n ; i ++){          // 10. 循环 n 次,处理当前层的所有节点TreeNode cur = q.poll();             // 11. 从队列头部取出一个节点 currow.add(cur.val);                    // 12. 将当前节点的值加入 row 列表if(cur.left != null) q.add(cur.left); // 13. 如果 cur 有左孩子,将左孩子加入队列if(cur.right != null) q.add(cur.right); // 14. 如果 cur 有右孩子,将右孩子加入队列}f++;                                     // 15. 层号计数器 f 加 1,准备处理下一层if(f % 2 == 0) Collections.reverse(row); // 16. 如果当前层号为偶数,反转 row 列表,实现之字形输出res.add(row);                            // 17. 将当前层的节点值列表加入最终结果 res}return res;                                  // 18. 返回层序遍历后的之字形结果列表}
}
  1. 使用两个栈,利用先进后出特性来反转
import java.util.*;public class Solution {public ArrayList<ArrayList<Integer>> Print (TreeNode pRoot) {TreeNode h = pRoot;                                  // 1. 用临时变量 h 保存根节点,避免直接修改形参ArrayList<ArrayList<Integer>> res = new ArrayList<>(); // 2. 创建最终结果容器 resif(h == null) return res;                            // 3. 空树直接返回空列表Stack<TreeNode> s1 = new Stack<TreeNode>();          // 4. 奇数层(从左到右)使用的栈Stack<TreeNode> s2 = new Stack<TreeNode>();          // 5. 偶数层(从右到左)使用的栈s1.push(h);                                          // 6. 根节点压入 s1,作为第 1 层(奇数层)while(!s1.isEmpty() || !s2.isEmpty()){               // 7. 只要任一栈非空就继续遍历ArrayList<Integer> row = new ArrayList<>();      // 8. 存放当前层节点值while(!s1.isEmpty()){                            // 9. 处理奇数层:s1 不为空TreeNode cur = s1.pop();                     // 10. 弹出栈顶节点row.add(cur.val);                            // 11. 记录节点值if(cur.left != null) s2.add(cur.left);       // 12. 左孩子先入 s2(下一层逆序用)if(cur.right != null) s2.add(cur.right);     // 13. 右孩子后入 s2}if(row.size() != 0)                              // 14. 若本层有节点res.add(new ArrayList<Integer>(row));        // 15. 深拷贝 row 加入到结果row.clear();                                     // 16. 清空 row,准备下一轮while(!s2.isEmpty()){                            // 17. 处理偶数层:s2 不为空TreeNode cur = s2.pop();                     // 18. 弹出栈顶节点row.add(cur.val);                            // 19. 记录节点值if(cur.right != null) s1.add(cur.right);     // 20. 右孩子先入 s1(下一层逆序用)if(cur.left != null) s1.add(cur.left);       // 21. 左孩子后入 s1}if(row.size() != 0)                              // 22. 若本层有节点res.add(new ArrayList<Integer>(row));        // 23. 深拷贝 row 加入到结果row.clear();                                     // 24. 清空 row,准备下一轮}return res;                                          // 25. 返回最终之字形层序遍历结果}
}

BM28 二叉树的最大深度

二叉树的最大深度_牛客题霸_牛客网
https://www.nowcoder.com/practice/8a2b2bf6c19b4f23a9bdb9b233eefa73?tpId=295&tqId=642&sourceUrl=%2Fexam%2Foj

import java.util.*;public class Solution {public int maxDepth(TreeNode root) {if (root == null) return 0; // 1. 如果根节点为空,直接返回深度为 0Queue<TreeNode> q = new LinkedList<TreeNode>(); // 2. 创建一个队列用于层序遍历int res = 0; // 3. 初始化最大深度q.add(root); // 4. 将根节点加入队列while (!q.isEmpty()) { // 5. 当队列不为空时,继续遍历int size = q.size(); // 6. 获取当前层的节点数for (int i = 0; i < size; i++) { // 7. 遍历当前层的所有节点TreeNode node = q.poll(); // 8. 弹出队列中的节点if (node.left != null) q.add(node.left); // 9. 如果左子节点不为空,加入队列if (node.right != null) q.add(node.right); // 10. 如果右子节点不为空,加入队列}res++; // 11. 每遍历完一层,深度加 1}return res; // 12. 返回最大深度}
}

BM29 二叉树中和为某一值的路径(一)

二叉树中和为某一值的路径(一)_牛客题霸_牛客网
https://www.nowcoder.com/practice/508378c0823c423baa723ce448cbfd0c?tpId=295&tqId=634&sourceUrl=%2Fexam%2Foj%3Fpage%3D1%26tab%3D%25E7%25AE%2597%25E6%25B3%2595%25E7%25AC%2594%25E9%259D%25A2%25E8%25AF%2595%25E7%25AF%2587%26topicId%3D295
2025年8月13日16:38:15 2025年8月13日16:48:21

  1. 递归
import java.util.*;public class Solution {public boolean hasPathSum (TreeNode root, int sum) {if(root == null) return false;// 1. 空节点说明之前的路径已走完,且未满足目标和,返回 falseif(root.left == null && root.right == null && root.val == sum) return true;// 2. 到达叶子节点:若剩余值等于当前节点值,则找到一条满足条件的路径,返回 true// 3. 递归检查左子树和右子树,目标和减去当前节点的值return hasPathSum(root.left, sum - root.val)   // 4. 向左子树继续寻找|| hasPathSum(root.right, sum - root.val); // 5. 向右子树继续寻找}
}
  1. 使用广搜,Pair记录从头节点到叶子的总值
import java.util.*;public class Solution {// 1. 辅助类 P:同时携带节点引用与该节点到根路径上的累加和class P {TreeNode node = null;  // 2. 当前节点int cursum = 0;        // 3. 从根到当前节点的路径和public P(TreeNode node, int cursum) {this.node = node;  // 4. 初始化节点this.cursum = cursum; // 5. 初始化累加和}}public boolean hasPathSum (TreeNode root, int sum) {// 6. 空树直接返回 falseif (root == null) return false;// 7. 创建队列,用于广度优先遍历Queue<P> q = new LinkedList<>();// 8. 将根节点及其值封装成 P 并入队P p = new P(root, root.val);q.add(p);// 9. 队列非空则继续处理while (!q.isEmpty()) {// 10. 取出队首元素P cur = q.poll();// 11. 若存在左孩子,创建新的 P 并入队if (cur.node.left != null) {q.add(new P(cur.node.left,                  // 12. 左孩子节点cur.cursum + cur.node.left.val  // 13. 新的累加和));}// 14. 若存在右孩子,创建新的 P 并入队if (cur.node.right != null) {q.add(new P(cur.node.right,                 // 15. 右孩子节点cur.cursum + cur.node.right.val // 16. 新的累加和));}// 17. 当前节点是叶子节点if (cur.node.left == null && cur.node.right == null) {// 18. 若累加和等于目标和,立即返回 trueif (sum == cur.cursum) return true;}}// 19. 遍历结束仍未找到符合条件的路径,返回 falsereturn false;}
}

BM30 二叉搜索树与双向链表

二叉搜索树与双向链表_牛客题霸_牛客网
https://www.nowcoder.com/practice/947f6eb80d944a84850b0538bf0ec3a5?tpId=295&tqId=23253&sourceUrl=%2Fexam%2Foj

  1. 递归中序遍历
import java.util.*;public class Solution {TreeNode head = null;  // 1. 最终要返回的双向链表头结点TreeNode pre  = null;  // 2. 指向当前已处理部分的尾结点(上一次访问的结点)public TreeNode Convert(TreeNode p) {if (p == null) return null;// 3. 空树直接返回 nullConvert(p.left);// 4. 递归处理左子树:把整棵左子树构造成双向链表if (pre == null) {// 5. 此时 pre == null 说明正在访问整棵树的最左叶子,即为链表头结点head = p;      // 6. 记录头结点pre  = p;      // 7. 当前结点成为已处理部分的尾结点} else {           // 8. 将当前结点 p 接到已处理链表的末尾pre.right = p; // 9. 尾结点的后继指向当前结点p.left  = pre; // 10. 当前结点的前驱指向尾结点pre = p;       // 11. 更新尾结点指针}Convert(p.right); // 12. 递归处理右子树:继续把右子树结点接到链表后面return head;// 13. 整棵树遍历完后,head 即为所求双向链表的头结点}
}
  1. 非递归中序遍历
import java.util.*;public class Solution {public TreeNode Convert(TreeNode p) {if(p == null) return null;                  // 1. 空树直接返回 nullStack<TreeNode> s = new Stack<TreeNode>();  // 2. 创建栈,用于非递归中序遍历TreeNode head = null;                       // 3. 最终要返回的双向链表头结点TreeNode pre = null;                        // 4. 指向当前已处理链表的尾结点boolean isHead = true;                      // 5. 标记是否第一次访问到最左结点(即链表头结点)while(p != null || !s.isEmpty()){           // 6. 外层循环:当 p 非空或栈非空时继续while(p != null){                       // 7. 内层循环:沿左子树一路到底s.push(p);                          // 8. 当前结点入栈p = p.left;                         // 9. 继续深入左孩子}p = s.pop();                            // 10. 弹出栈顶结点(此时为最左未访问结点)if(isHead){                             // 11. 如果是第一次访问(最左结点)head = p;                           // 12. 记录头结点pre = p;                            // 13. 当前结点成为已处理链表的尾结点isHead = false;                     // 14. 标记已处理过头结点}else{                                  // 15. 否则,已有部分链表pre.right = p;                      // 16. 尾结点的后继指向当前结点p.left = pre;                       // 17. 当前结点的前驱指向尾结点pre = p;                            // 18. 更新尾结点指针}p = p.right;                            // 19. 转向当前结点的右子树(可能为空)}return head;                                // 20. 返回构造好的双向链表头结点}
}

BM31 对称的二叉树

对称的二叉树_牛客题霸_牛客网
https://www.nowcoder.com/practice/ff05d44dfdb04e1d83bdbdab320efbcb?tpId=295&tqId=23253&sourceUrl=%2Fexam%2Foj
2025年8月14日14:05:33 2025年8月14日14:22:40

  1. 层序遍历 + 回文/对称
import java.util.*;public class Solution {int INF = 0x3f3f3f;                       // 1. 用一个极大值作为空节点的占位值TreeNode emptyNode = new TreeNode(INF);   // 2. 创建统一的空节点对象,用于缺失左右孩子时的占位// 3. 检查给定层序列表是否为回文(对称)boolean check(ArrayList<Integer> list){int n = list.size();                  // 4. 当前层节点个数for(int i = 0 ; i < n ; i ++){        // 5. 双指针对撞比较if(!list.get(i).equals(list.get(n - 1 - i))) return false; // 6. 发现不对称立即返回 false}return true;                          // 7. 全部对称则返回 true}public boolean isSymmetrical (TreeNode p) {if(p == null) return true;            // 8. 空树视为对称,直接返回 trueQueue<TreeNode> q = new LinkedList<>(); // 9. 队列用于层序(广度优先)遍历q.offer(p);                           // 10. 根节点入队while(!q.isEmpty()){                  // 11. 逐层处理直到队列为空int n = q.size();                 // 12. 当前层的节点数量ArrayList<Integer> row = new ArrayList<>(); // 13. 存放当前层的值(含占位值)for(int i = 0; i < n ; i ++){     // 14. 处理当前层的所有节点TreeNode cur = q.poll();      // 15. 取出队首节点if(!cur.equals(emptyNode)){   // 16. 若非空节点// 17. 左孩子存在则入队真实节点,否则入队空节点占位q.add(cur.left != null ? cur.left : emptyNode);// 18. 右孩子存在则入队真实节点,否则入队空节点占位q.add(cur.right != null ? cur.right : emptyNode);}row.add(cur.val);             // 19. 记录当前节点值(含占位值)}// 20. 只要某层不对称,整棵树就不对称if(!check(row)) return false;}return true;                          // 21. 所有层都对称,返回 true}
}
  1. 递归写法
import java.util.*;public class Solution {// 1. 辅助函数:递归判断以 p1、p2 为根的两棵子树是否镜像对称boolean chk(TreeNode p1, TreeNode p2) {// 2. 两棵树同时为空 → 对称if (p1 == null && p2 == null) return true;// 3. 仅有一棵为空 → 不对称if (p1 == null || p2 == null) return false;// 4. 节点值不相等 → 不对称if (p1.val != p2.val) return false;// 5. 递归检查:p1 的左子树与 p2 的右子树、p1 的右子树与 p2 的左子树是否都镜像对称return chk(p1.left, p2.right) && chk(p1.right, p2.left);}public boolean isSymmetrical (TreeNode p) {// 6. 以整棵树的根节点同时作为左、右子树,调用 chk 判断整体是否对称return chk(p, p);}
}

BM32 合并二叉树

合并二叉树_牛客题霸_牛客网
https://www.nowcoder.com/practice/7298353c24cc42e3bd5f0e0bd3d1d759?tpId=295&tags=&title=&difficulty=0&judgeStatus=0&rp=0&sourceUrl=%2Fexam%2Foj

import java.util.*;public class Solution {public TreeNode mergeTrees (TreeNode t1, TreeNode t2) {// 1. 如果 t1 为空,直接返回 t2 作为合并结果if (t1 == null) return t2;// 2. 如果 t2 为空,直接返回 t1 作为合并结果if (t2 == null) return t1;// 3. 新建节点 head,其值为 t1 与 t2 节点值之和TreeNode head = new TreeNode(t1.val + t2.val);// 4. 递归合并 t1 与 t2 的左子树,结果挂到 head.lefthead.left = mergeTrees(t1.left, t2.left);// 5. 递归合并 t1 与 t2 的右子树,结果挂到 head.righthead.right = mergeTrees(t1.right, t2.right);// 6. 返回合并后的根节点return head;}
}

BM33 二叉树的镜像

二叉树的镜像_牛客题霸_牛客网
https://www.nowcoder.com/practice/a9d0ecbacef9410ca97463e4a5c83be7?tpId=295&tqId=1374963&sourceUrl=%2Fexam%2Foj

  1. 直接递归
import java.util.*;public class Solution {public TreeNode Mirror (TreeNode p) {if (p == null) return null; // 1. 若当前节点为空,直接返回 nullTreeNode left = Mirror(p.left);// 2. 递归翻转左子树,得到翻转后的左子树(此时已变成右子树)TreeNode right = Mirror(p.right);// 3. 递归翻转右子树,得到翻转后的右子树(此时已变成左子树)p.left = right;// 4. 将当前节点的左指针指向翻转后的右子树p.right = left;// 5. 将当前节点的右指针指向翻转后的左子树return p;        // 6. 返回已完成翻转的当前节点}
}
  1. 借助辅助空间,栈
import java.util.*;public class Solution {public TreeNode Mirror (TreeNode p) {if (p == null) return null;         // 1. 空树直接返回Stack<TreeNode> s = new Stack<TreeNode>();  // 2. 创建栈用于迭代s.push(p);                          // 3. 根节点入栈while (!s.isEmpty()) {              // 4. 栈非空则继续处理TreeNode cur = s.pop();         // 5. 弹出当前待处理节点if (cur.left != null) s.push(cur.left); // 6. 左孩子入栈if (cur.right != null) s.push(cur.right); // 7. 右孩子入栈TreeNode temp = cur.left;       // 8. 暂存原左子树cur.left = cur.right;           // 9. 左指针指向原右子树cur.right = temp;               // 10. 右指针指向原左子树}return p;                           // 11. 返回翻转后的根节点}
}

BM34 判断是不是二叉搜索树

判断是不是二叉搜索树_牛客题霸_牛客网
https://www.nowcoder.com/practice/a69242b39baf45dea217815c7dedb52b?tpId=295&tags=&title=&difficulty=0&judgeStatus=0&rp=0&sourceUrl=%2Fexam%2Foj

  1. 栈模拟,然后中序遍历是否单调
import java.util.*;public class Solution {public boolean isValidBST (TreeNode root) {if (root == null) return true;                     // 1. 空树视为合法 BSTStack<TreeNode> s = new Stack<TreeNode>();         // 2. 创建栈,用于中序遍历ArrayList<Integer> list = new ArrayList<Integer>();// 3. 存放中序遍历得到的节点值TreeNode head = root;                              // 4. 当前遍历指针,初始指向根节点while (head != null || !s.isEmpty()) {             // 5. 只要指针非空或栈非空就继续while (head != null) {                         // 6. 一路向左走到头s.push(head);                              // 7. 沿途节点入栈head = head.left;                          // 8. 继续深入左子树}head = s.pop();                                // 9. 弹出栈顶(最左未访问节点)list.add(head.val);                            // 10. 记录节点值head = head.right;                             // 11. 转向右子树}for (int i = 1; i < list.size(); i++) { // 12. 检查中序序列是否严格递增if (list.get(i) <= list.get(i - 1)) return false; // 13. 出现非递增即非 BST}return true;                                       // 14. 全部递增,是合法 BST}
}
  1. 递归
import java.util.*;public class Solution {int pre = Integer.MIN_VALUE;        // 1 保存前一个节点的值,初始化为整型最小值public boolean isValidBST (TreeNode root) {if(root == null) return true;    // 2 空树被认为是合法的 BSTif(!isValidBST(root.left)) return false; // 3 先递归检查左子树是否合法if(root.val < pre) return false; // 4 若当前节点值不大于前一个节点值,则违反 BST 性质pre = root.val;                 // 5 更新 pre 为当前节点值,准备与下一个节点比较return isValidBST(root.right);  // 6 最后递归检查右子树是否合法}
}

BM35 判断是不是完全二叉树

判断是不是完全二叉树_牛客题霸_牛客网
https://www.nowcoder.com/practice/8daa4dff9e36409abba2adbe413d6fae?tpId=295&tags=&title=&difficulty=0&judgeStatus=0&rp=0&sourceUrl=%2Fexam%2Foj

import java.util.*;public class Solution {public boolean isCompleteTree (TreeNode root) {if(root == null) return true;                // 1 空树视为完全二叉树Queue<TreeNode> q = new LinkedList<TreeNode>(); // 2 创建队列用于层序遍历q.offer(root);                               // 3 根节点入队boolean notOk = false;                       // 4 标记是否已遇到空节点while(!q.isEmpty()){                         // 5 队列非空时循环TreeNode cur = q.poll();                 // 6 取出队首节点if(cur == null) {                        // 7 遇到空节点notOk = true;                        // 8 置位标记continue;                            // 9 继续处理后续节点}if(notOk) return false;                  // 10 若之前已遇到空节点且当前节点非空,则不完整q.offer(cur.left);                       // 11 左孩子入队(可为 null)q.offer(cur.right);                      // 12 右孩子入队(可为 null)}return true;                                 // 13 全部遍历完未发现违规,返回 true}
}

BM36 判断是不是平衡二叉树

判断是不是平衡二叉树_牛客题霸_牛客网
https://www.nowcoder.com/practice/8b3b95850edb4115918ecebdf1b4d222?tpId=295&tags=&title=&difficulty=0&judgeStatus=0&rp=0&sourceUrl=%2Fexam%2Foj

import java.util.*;public class Solution {boolean isOk = true;                         // 1 全局标志,记录整棵树是否平衡public int depth(TreeNode p){                // 2 后序遍历求当前子树高度if(p == null){                           // 3 空节点高度为 0return 0;}int l = depth(p.left);                   // 4 递归获取左子树高度int r = depth(p.right);                  // 5 递归获取右子树高度if(Math.abs(l - r) > 1){                 // 6 左右高度差超过 1,则不平衡isOk = false;}return Math.max(l, r) + 1;               // 7 返回当前子树高度}public boolean IsBalanced_Solution (TreeNode pRoot) {int d = depth(pRoot);                    // 8 触发整棵树的遍历与标记return isOk;                             // 9 返回是否平衡的最终结果}
}
  1. 方法一 剪枝
import java.util.*;public class Solution {boolean isOk = true;                // 1 全局标志,标记整棵树是否平衡public int depth(TreeNode p){       // 2 后序遍历求子树高度,不平衡时直接返回-1剪枝if(p == null){                  // 3 空节点高度为0return 0;}int l = depth(p.left);          // 4 递归求左子树高度if(l == -1) return -1;          // 5 左子树不平衡,向上传递-1int r = depth(p.right);         // 6 递归求右子树高度if(r == -1) return -1;          // 7 右子树不平衡,向上传递-1if(Math.abs(l - r) > 1){        // 8 左右高度差大于1,当前子树不平衡isOk = false;               // 9 置位全局不平衡标志return -1;                  // 10 向上返回-1表示不平衡}return Math.max(l, r) + 1;      // 11 当前子树平衡,返回其高度}public boolean IsBalanced_Solution (TreeNode pRoot) {int d = depth(pRoot);           // 12 触发整棵树的后序遍历与剪枝检查return isOk;                    // 13 返回最终是否平衡的结果}
}

BM37 二叉搜索树的最近公共祖先

二叉搜索树的最近公共祖先_牛客题霸_牛客网
https://www.nowcoder.com/practice/d9820119321945f588ed6a26f0a6991f?tpId=295&tags=&title=&difficulty=0&judgeStatus=0&rp=0&sourceUrl=%2Fexam%2Foj

  1. 遍历两个节点的路径
import java.util.*;public class Solution {ArrayList<Integer> getPath(TreeNode r, int n){ArrayList<Integer> res = new ArrayList<Integer>(); // 1. 创建结果列表,存储路径上的节点值TreeNode p = r; // 2. 从根节点开始while(p.val != n){ // 3. 遍历二叉搜索树,直到找到目标节点 nres.add(p.val); // 4. 将当前节点值加入路径if(n < p.val){ // 5. 如果目标值小于当前节点值,向左子树移动p = p.left;}else { // 6. 如果目标值大于当前节点值,向右子树移动p = p.right;}}  res.add(p.val); // 7. 将目标节点值加入路径return res; // 8. 返回完整的路径}public int lowestCommonAncestor (TreeNode r, int p, int q) {ArrayList<Integer> ppath = getPath(r,p); // 9. 获取从根节点到节点 p 的路径ArrayList<Integer> qpath = getPath(r,q); // 10. 获取从根节点到节点 q 的路径int ans = 0; // 11. 初始化最低公共祖先的值for(int i = 0 ; i  < ppath.size() && i < qpath.size(); i ++){ // 12. 遍历两条路径,找到最后一个相同的节点int x = ppath.get(i); // 13. 获取路径 p 中的当前节点值int y = qpath.get(i); // 14. 获取路径 q 中的当前节点值if(x == y) ans = ppath.get(i); // 15. 如果两个值相同,更新最低公共祖先else break; // 16. 如果不同,停止遍历}return ans; // 17. 返回最低公共祖先的值}
}
  1. 用一个set存 遍历到最后一个一样的节点
import java.util.*;public class Solution {public int lowestCommonAncestor (TreeNode r, int p, int q) {Set<Integer> s = new HashSet<Integer>(); // 1. 创建一个集合,用于存储从根节点到节点 p 的路径上的节点值TreeNode cur = r; // 2. 从根节点开始while(cur.val != p){ // 3. 遍历二叉搜索树,直到找到节点 ps.add(cur.val); // 4. 将当前节点值加入集合if(cur.val > p) cur = cur.left; // 5. 如果当前节点值大于 p,向左子树移动else cur = cur.right; // 6. 如果当前节点值小于 p,向右子树移动}s.add(cur.val); // 7. 将节点 p 的值加入集合cur = r; // 8. 重新从根节点开始int res = -1; // 9. 初始化最低公共祖先的值为 -1while(cur.val != q){ // 10. 遍历二叉搜索树,直到找到节点 qif(s.contains(cur.val)) res = cur.val; // 11. 如果当前节点值在集合中,更新最低公共祖先if(cur.val > q) cur = cur.left; // 12. 如果当前节点值大于 q,向左子树移动else cur = cur.right; // 13. 如果当前节点值小于 q,向右子树移动}return res == -1 ? q : res; // 14. 如果 res 仍为 -1,说明 q 本身就是最低公共祖先,否则返回 res}
}

BM38 在二叉树中找到两个节点的最近公共祖先

在二叉树中找到两个节点的最近公共祖先_牛客题霸_牛客网
https://www.nowcoder.com/practice/e0cc33a83afe4530bcec46eba3325116?tpId=295&tags=&title=&difficulty=0&judgeStatus=0&rp=0&sourceUrl=%2Fexam%2Foj

  1. dfs + 路径比较
import java.util.*;public class Solution {boolean ok = false; // 剪枝标记void depth(TreeNode p,int t,ArrayList<Integer> cur){if(p == null || ok) return; // 1. 如果当前节点为空或已找到目标节点,直接返回cur.add(p.val); // 2. 将当前节点值加入路径if(p.val == t){ // 3. 如果当前节点值等于目标值 tok = true; // 4. 标记找到目标节点return;}depth(p.left,t,cur); // 5. 递归遍历左子树depth(p.right,t,cur); // 6. 递归遍历右子树if(ok) return; // 7. 如果已找到目标节点,直接返回cur.remove(cur.size() - 1); // 8. 回溯,移除当前节点值}public int lowestCommonAncestor (TreeNode root, int o1, int o2) {ArrayList<Integer> l1 = new ArrayList<Integer>(); // 9. 存储从根节点到 o1 的路径ArrayList<Integer> l2 = new ArrayList<Integer>(); // 10. 存储从根节点到 o2 的路径ok = false; // 11. 重置标志变量depth(root,o1,l1); // 12. 获取从根节点到 o1 的路径ok = false; // 13. 重置标志变量depth(root,o2,l2); // 14. 获取从根节点到 o2 的路径int res = 0; // 15. 初始化最低公共祖先的值for(int i = 0 ; i < l1.size() && i < l2.size(); i ++){ // 16. 遍历两条路径,找到最后一个相同的节点if(l1.get(i).equals(l2.get(i))) res = l1.get(i); // 17. 如果两个路径上的节点值相同,更新最低公共祖先else break; // 18. 如果不同,停止遍历}return res; // 19. 返回最低公共祖先的值}
}
  1. 递归
import java.util.*;public class Solution {public int lowestCommonAncestor(TreeNode r, int o1, int o2) {if (r == null) return -1; // 1. 如果当前节点为空,返回 -1 表示未找到if (r.val == o1 || r.val == o2) return r.val;// 2. 如果当前节点值等于 o1 或 o2,返回当前节点值int lf = lowestCommonAncestor(r.left, o1, o2); // 3. 递归在左子树中查找最低公共祖先int rh = lowestCommonAncestor(r.right, o1, o2); // 4. 递归在右子树中查找最低公共祖先if (lf == -1) return rh; // 5. 如果左子树未找到,返回右子树的结果if (rh == -1) return lf; // 6. 如果右子树未找到,返回左子树的结果return r.val; // 7. 如果左右子树都找到了,当前节点就是最低公共祖先}
}

BM39 序列化二叉树

序列化二叉树_牛客题霸_牛客网
https://www.nowcoder.com/practice/cf7e25aa97c04cc1a68c8f040e71fb84?tpId=295&tqId=23455&sourceUrl=%2Fexam%2Foj

  1. 广搜遍历 + StringBuilder
import java.util.*;public class Solution {int INF = Integer.MAX_VALUE; // 1. 定义一个无穷大值,用于标记空节点TreeNode emptyNode = new TreeNode(INF); // 2. 创建一个值为 INF 的空节点// 3. 序列化二叉树String Serialize(TreeNode r) {if (r == null) return ""; // 4. 如果根节点为空,返回空字符串StringBuilder sb = new StringBuilder(); // 5. 创建一个字符串构建器用于存储序列化结果Deque<TreeNode> dq = new ArrayDeque<>(); // 6. 创建一个双端队列用于层序遍历dq.addLast(r); // 7. 将根节点加入队列while (!dq.isEmpty()) { // 8. 遍历队列直到为空TreeNode cur = dq.pollFirst(); // 9. 取出队首节点sb.append(cur.val + "_"); // 10. 将当前节点值追加到字符串构建器if (!cur.equals(emptyNode)) { // 11. 如果当前节点不是空节点dq.addLast(cur.left != null ? cur.left : emptyNode); // 12. 将左子节点加入队列(若为空则加入空节点)dq.addLast(cur.right != null ? cur.right : emptyNode); // 13. 将右子节点加入队列(若为空则加入空节点)}}return sb.toString(); // 14. 返回序列化后的字符串}// 15. 反序列化二叉树TreeNode Deserialize(String str) {if (str.equals("")) return null; // 16. 如果字符串为空,返回空节点String[] s = str.split("_"); // 17. 将字符串按 "_" 分割成数组int n = s.length; // 18. 获取数组长度TreeNode p = new TreeNode(Integer.parseInt(s[0])); // 19. 创建根节点Deque<TreeNode> dq = new ArrayDeque<TreeNode>(); // 20. 创建一个双端队列用于层序遍历dq.addLast(p); // 21. 将根节点加入队列for (int i = 1; i < n - 1; i += 2) { // 22. 遍历数组,每次处理两个子节点TreeNode cur = dq.pollFirst(); // 23. 取出队首节点int l = Integer.parseInt(s[i]), r = Integer.parseInt(s[i + 1]); // 24. 获取左右子节点的值if (l != INF) { // 25. 如果左子节点值不是 INFcur.left = new TreeNode(l); // 26. 创建左子节点dq.addLast(cur.left); // 27. 将左子节点加入队列}if (r != INF) { // 28. 如果右子节点值不是 INFcur.right = new TreeNode(r); // 29. 创建右子节点dq.addLast(cur.right); // 30. 将右子节点加入队列}}return p; // 31. 返回重建的二叉树根节点}
}
  1. 递归
import java.util.*;public class Solution {static int idx = 0; // 1. 静态变量,用于记录反序列化时的字符串索引位置// 2. 序列化辅助函数,递归地将二叉树序列化为字符串void SerializeFuction(TreeNode p, StringBuilder sb) {if (p == null) { // 3. 如果当前节点为空,追加 '#' 表示空节点sb.append('#');return;}sb.append(p.val).append("_"); // 4. 将当前节点值追加到字符串构建器,并添加分隔符 "_"SerializeFuction(p.left, sb); // 5. 递归序列化左子树SerializeFuction(p.right, sb); // 6. 递归序列化右子树}// 7. 序列化主函数,调用辅助函数完成序列化String Serialize(TreeNode r) {if (r == null) return "#"; // 8. 如果根节点为空,返回特殊字符 "#" 表示空树StringBuilder res = new StringBuilder(); // 9. 创建字符串构建器用于存储序列化结果SerializeFuction(r, res); // 10. 调用辅助函数进行序列化return res.toString(); // 11. 返回序列化后的字符串}// 12. 反序列化辅助函数,递归地从字符串中重建二叉树TreeNode DeserializeFuction(String str) {if (str.charAt(idx) == '#') { // 13. 如果当前字符是 '#',表示空节点idx++; // 14. 索引后移return null;}int val = 0; // 15. 初始化节点值// 16. 解析当前节点的值,直到遇到分隔符 "_" 或字符串结束while (str.charAt(idx) != '_' && idx != str.length()) {val = val * 10 + (str.charAt(idx) - '0'); // 17. 将字符转换为数字并累加idx++; // 18. 索引后移}TreeNode p = new TreeNode(val); // 19. 创建当前节点if (idx == str.length()) return p; // 20. 如果已到达字符串末尾,返回当前节点else idx++; // 21. 跳过分隔符 "_"p.left = DeserializeFuction(str); // 22. 递归重建左子树p.right = DeserializeFuction(str); // 23. 递归重建右子树return p; // 24. 返回重建的当前节点}// 25. 反序列化主函数,调用辅助函数完成反序列化TreeNode Deserialize(String str) {if (str.equals("#")) return null; // 26. 如果字符串为 "#",返回空节点idx = 0; // 27. 重置索引TreeNode res = DeserializeFuction(str); // 28. 调用辅助函数进行反序列化return res; // 29. 返回重建的二叉树根节点}
}

BM40 重建二叉树

重建二叉树_牛客题霸_牛客网
https://www.nowcoder.com/practice/8a19cbe657394eeaac2f6ea9b0f6fcf6?tpId=295&tags=&title=&difficulty=0&judgeStatus=0&rp=0&sourceUrl=%2Fexam%2Foj

  1. 递归
import java.util.*;public class Solution {public TreeNode reConstructBinaryTree(int[] pre, int[] vin) {int n = pre.length; // 1. 获取前序遍历数组的长度int m = vin.length; // 2. 获取中序遍历数组的长度if (n == 0 || m == 0) return null; // 3. 如果数组长度为 0,返回空节点TreeNode r = new TreeNode(pre[0]); // 4. 根据前序遍历的第一个元素创建根节点for (int i = 0; i < vin.length; i++) { // 5. 在中序遍历数组中找到根节点的位置if (pre[0] == vin[i]) {// 6. 递归重建左子树,使用前序遍历的 [1, i+1] 和中序遍历的 [0, i]r.left = reConstructBinaryTree(Arrays.copyOfRange(pre, 1, i + 1), Arrays.copyOfRange(vin, 0, i));// 7. 递归重建右子树,使用前序遍历的 [i+1, n] 和中序遍历的 [i+1, m]r.right = reConstructBinaryTree(Arrays.copyOfRange(pre, i + 1, n), Arrays.copyOfRange(vin, i + 1, m));break; // 8. 找到根节点后退出循环}}return r; // 9. 返回重建的二叉树根节点}
}
  1. 栈遍历
import java.util.*;public class Solution {public TreeNode reConstructBinaryTree(int[] pre, int[] vin) {int n = pre.length; // 1. 获取前序遍历数组的长度int m = pre.length; // 2. 获取中序遍历数组的长度if (n == 0 || m == 0) return null; // 3. 如果数组长度为 0,返回空节点Stack<TreeNode> s = new Stack<TreeNode>(); // 4. 创建一个栈,用于辅助重建二叉树TreeNode r = new TreeNode(pre[0]); // 5. 根据前序遍历的第一个元素创建根节点TreeNode cur = r; // 6. 当前节点指针初始化为根节点for (int i = 1, j = 0; i < n; i++) { // 7. 遍历前序遍历数组,从第二个元素开始if (cur.val != vin[j]) { // 8. 如果当前节点不是中序遍历中的当前节点cur.left = new TreeNode(pre[i]); // 9. 创建左子节点s.push(cur); // 10. 将当前节点压入栈cur = cur.left; // 11. 将当前节点指针移动到左子节点} else { // 12. 如果当前节点是中序遍历中的当前节点j++; // 13. 中序遍历指针后移while (!s.isEmpty() && s.peek().val == vin[j]) { // 14. 弹出栈中所有匹配的节点cur = s.pop(); // 15. 更新当前节点指针j++; // 16. 中序遍历指针后移}cur.right = new TreeNode(pre[i]); // 17. 创建右子节点cur = cur.right; // 18. 将当前节点指针移动到右子节点}}return r; // 19. 返回重建的二叉树根节点}
}

BM41 输出二叉树的右视图

输出二叉树的右视图_牛客题霸_牛客网
https://www.nowcoder.com/practice/c9480213597e45f4807880c763ddd5f0?tpId=295&tqId=1073834&sourceUrl=%2Fexam%2Foj

  1. 递归建树 , 一个哈希表维护最深节点,两个栈分别维护节点和深度
import java.util.*;public class Solution {// 1. 根据前序和中序遍历结果重建二叉树TreeNode buildTree(int[] pre, int[] in, int preStart, int preEnd, int inStart, int inEnd) {if (preStart > preEnd || inStart > inEnd) return null; // 2. 如果索引范围无效,返回空节点TreeNode p = new TreeNode(pre[preStart]); // 3. 根据前序遍历的第一个元素创建根节点int idx = inStart; // 4. 初始化中序遍历中根节点的索引while (idx <= inEnd && in[idx] != pre[preStart]) idx++; // 5. 在中序遍历中找到根节点的位置int leftSize = idx - inStart; // 6. 计算左子树的大小// 7. 递归构建左子树p.left = buildTree(pre, in, preStart + 1, preStart + leftSize, inStart, idx - 1);// 8. 递归构建右子树p.right = buildTree(pre, in, preStart + leftSize + 1, preEnd, idx + 1, inEnd);return p; // 9. 返回重建的子树根节点}// 10. 获取二叉树的右侧视图ArrayList<Integer> rightSideView(TreeNode r) {ArrayList<Integer> res = new ArrayList<>(); // 11. 存储结果if (r == null) return res; // 12. 如果根节点为空,返回空列表Queue<TreeNode> q = new LinkedList<>(); // 13. 使用队列实现广度优先搜索q.add(r); // 14. 将根节点入队while (!q.isEmpty()) { // 15. 遍历队列直到为空int size = q.size(); // 16. 获取当前层的节点数for (int i = 0; i < size; i++) { // 17. 遍历当前层的所有节点TreeNode cur = q.poll(); // 18. 弹出队首节点if (i == size - 1) { // 19. 如果是当前层的最后一个节点res.add(cur.val); // 20. 添加到结果列表}if (cur.left != null) q.add(cur.left); // 21. 左子节点入队if (cur.right != null) q.add(cur.right); // 22. 右子节点入队}}return res; // 23. 返回结果}// 24. 主函数,根据前序和中序遍历结果,返回右侧视图public int[] solve(int[] pre, int[] in) {int n = pre.length; // 25. 前序遍历数组长度int m = in.length; // 26. 中序遍历数组长度if (m == 0 || n == 0) return new int[0]; // 27. 如果数组为空,返回空数组TreeNode r = buildTree(pre, in, 0, n - 1, 0, m - 1); // 28. 重建二叉树ArrayList<Integer> tmp = rightSideView(r); // 29. 获取右侧视图int[] res = new int[tmp.size()]; // 30. 转换为数组for (int i = 0; i < tmp.size(); i++) res[i] = tmp.get(i); // 31. 填充数组return res; // 32. 返回结果}
}
  1. 库函数
import java.util.*;public class Solution {// 1. 根据前序和中序遍历结果重建二叉树TreeNode buildTree(int[] pre, int l1, int r1, int[] in, int l2, int r2) {if (l1 > r1 || l2 > r2) return null; // 2. 如果索引范围无效,返回空节点TreeNode p = new TreeNode(pre[l1]); // 3. 根据前序遍历的第一个节点创建根节点int idx = 0; // 4. 初始化中序遍历中根节点的索引for (int i = l2; i <= r2; i++) { // 5. 在中序遍历中找到根节点的位置if (in[i] == pre[l1]) {idx = i; // 6. 记录根节点的索引break;}}int lsize = idx - l2; // 7. 计算左子树的大小int rsize = r2 - idx; // 8. 计算右子树的大小// 9. 递归构建左子树p.left = buildTree(pre, l1 + 1, l1 + lsize, in, l2, l2 + lsize - 1);// 10. 递归构建右子树p.right = buildTree(pre, r1 - rsize + 1, r1, in, idx + 1, r2);return p; // 11. 返回重建的子树根节点}// 12. 获取二叉树的右侧视图ArrayList<Integer> rightSideView(TreeNode r) {Map<Integer, Integer> mp = new HashMap<Integer, Integer>(); // 13. 用于存储每层最右侧的节点值int maxdepth = -1; // 14. 记录最大深度Stack<TreeNode> s1 = new Stack<TreeNode>(); // 15. 存储节点的栈Stack<Integer> s2 = new Stack<Integer>(); // 16. 存储节点深度的栈s1.push(r); // 17. 将根节点入栈s2.push(0); // 18. 根节点深度为 0while (!s1.isEmpty()) { // 19. 遍历栈直到为空TreeNode cur = s1.pop(); // 20. 弹出当前节点int curdepth = s2.pop(); // 21. 弹出当前节点深度if (cur != null) {maxdepth = Math.max(maxdepth, curdepth); // 22. 更新最大深度if (mp.get(curdepth) == null) { // 23. 如果当前深度没有记录节点值mp.put(curdepth, cur.val); // 24. 记录当前节点值}s1.push(cur.left); // 25. 左子节点入栈s1.push(cur.right); // 26. 右子节点入栈s2.push(curdepth + 1); // 27. 左子节点深度 +1s2.push(curdepth + 1); // 28. 右子节点深度 +1}}ArrayList<Integer> res = new ArrayList<>(); // 29. 存储结果for (int i = 0; i <= maxdepth; i++) { // 30. 按深度顺序添加节点值res.add(mp.get(i));}return res; // 31. 返回结果}// 32. 主函数,根据前序和中序遍历结果,返回右侧视图public int[] solve(int[] pre, int[] in) {int n = pre.length; // 33. 前序遍历数组长度int m = in.length; // 34. 中序遍历数组长度if (m == 0 || n == 0) return new int[0]; // 35. 如果数组为空,返回空数组TreeNode r = buildTree(pre, 0, n - 1, in, 0, m - 1); // 36. 重建二叉树ArrayList<Integer> tmp = rightSideView(r); // 37. 获取右侧视图int[] res = new int[tmp.size()]; // 38. 转换为数组for (int i = 0; i < tmp.size(); i++) res[i] = tmp.get(i); // 39. 填充数组return res; // 40. 返回结果}
}
http://www.dtcms.com/a/336956.html

相关文章:

  • 深入解析StatefulSet与K8s服务管理
  • 集成电路学习:什么是Face Detection人脸检测
  • 多线程初阶-线程安全 (面试和工作的重点!!!)
  • Vue2篇——第六章 Vue 路由(VueRouter)全解析
  • Linux系统网络排查工具总结
  • org.apache.kafka.clients 和 org.springframework.kafka 的区别
  • kafka 发送消息有哪些模式?各自的应用场景是什么?
  • Elasticsearch全文检索中文分词:IK分词器详解与Docker环境集成
  • AI编程工具对决:Kilo vs Augment 开发Flutter俄罗斯方块游戏实战对比
  • 【AI论文】UI-Venus技术报告:借助强化微调(RFT)打造高性能用户界面(UI)代理
  • 手写Spring容器核心原理
  • 加密资产投资的六种策略:稳定币合规后的 Web3 投资和 RWA
  • 杂记 05
  • ARM 架构简明教程学习笔记
  • 微信原生小程序的一次gulp构建
  • DevExtreme Angular UI控件更新:引入全新严格类型配置组件
  • Kafka的ISR、OSR、AR详解
  • Rust学习笔记(六)|Rust 中的常用集合(Vector、String、HashMap)
  • Linux网络服务(一)——计算机网络参考模型与子网划分
  • 计算机网络:2、TCP和UDP
  • Golang context
  • CentOS 7 LAMP快速部署WordPress指南
  • 云原生Ansible渗透场景(⾃动化的运维⼯具)
  • Ansible企业及实战
  • OVS:除了Geneve和VXLAN,还有哪些虚拟化网络协议?
  • 云计算:企业数字化转型的核心引擎
  • 传统方式部署(RuoYi-Cloud)微服务
  • 一套GoldenGate → Kafka → Flink → MySQL 的端到端增量同步方案
  • 云计算学习100天-第17天
  • Linux学习-(进程间,线程间通信)