二叉树算法—Java版
创始人
2025-05-28 15:46:48

遍历方式

  • 深度优先遍历(一般采用递归或栈实现)

    • 前序遍历(递归法,迭代法)
    • 中序遍历(递归法,迭代法)
    • 后序遍历(递归法,迭代法)
  • 广度优先遍历(一般采用队列实现)

    • 层次遍历(迭代法)

代码实现

  • Java定义树节点

    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 List preorderTraversal(TreeNode root){ArrayList result = new ArrayList<>();//preorder(root,result); //前序遍历//inorder(root,result); //中序遍历postorder(root,result); //后序遍历return result;}public void preorder(TreeNode root, List result){// 前序遍历if(root==null){return;}result.add(root.val);preorder(root.left,result);preorder(root.right,result);}public void inorder(TreeNode root , List result){//中序遍历if(root==null){return;}inorder(root.left,result);result.add(root.val);inorder(root.right,result);}public void postorder(TreeNode root, List result){//后序遍历if(root==null){return;}postorder(root.left,result);postorder(root.right,result);result.add(root.val);}}

迭代使用栈替代递归

class Solution {public List preorderTraversal(TreeNode root) {// 前序遍历List result = new ArrayList<>();if (root == null) {return result;}Stack stack = new Stack<>();stack.push(root);while (!stack.isEmpty()) {TreeNode node = stack.pop();result.add(node.val);if (root.right != null) {stack.add(root.right);}if (root.left != null) {stack.add(root.left);}}return result;}public List postorderTraversal(TreeNode root) {// 后序遍历,中左右,反转List result = new ArrayList<>();if (root == null) {return result;}Stack stack = new Stack<>();stack.push(root);while (!stack.isEmpty()) {TreeNode node = stack.pop();result.add(node.val);if (root.left != null) {stack.add(root.left);}if (root.right != null) {stack.add(root.right);}}Collections.reverse(result);return result;}}
  • 广度优先遍历(层次遍历)

    • 层次遍历

      将每一层依次入队,每一个节点出队都要让它的所有子节点入队。

      public List> levelOrder(TreeNode root){ArrayDeque queue = new ArrayDeque<>();ArrayList> result = new ArrayList<>();if(root==null){return result;}queue.addLast(root);while (!queue.isEmpty()){int size = queue.size();ArrayList layer = new ArrayList<>();for (int i = 0; i < size; i++) {TreeNode node = queue.pollFirst();layer.add(node.val);if(node.left!=null){queue.add(node.left);}if(node.right!=null){queue.add(node.right);}}result.add(layer);}return result;}
      
  • LeetCode练习题

    • 226. 翻转二叉树

      public TreeNode invertTree(TreeNode root) {//只需要将子节点左右反转即可// 前序遍历-栈实现if(root==null){return null;}Stack stack = new Stack<>();stack.add(root);while (!stack.isEmpty()){TreeNode node = stack.pop();TreeNode temp = node.left;node.left = node.right;node.right = temp;if(node.left!=null){stack.add(node.left);}if(node.right!=null){stack.add(node.right);}}return  root;
      }
      
    • 101. 对称二叉树

       public boolean compare(TreeNode left,TreeNode right){if(left==null && right!=null){return false;} else if (left != null && right == null) {return false;} else if(left==null && right==null){return true;} else if (left!=null && right!=null) {return left.val==right.val && compare(left.left,right.right) && compare(left.right,right.left);}return false;}public boolean isSymmetric(TreeNode root) {//两种解法 1、递归法:两个子树的 外侧树相等,内侧树相等if(root==null){return true;}return compare(root.left,root.right);}
      
      public boolean isSymmetric2(TreeNode root) {//2、队列法,每次进队2个节点,出队2个节点ArrayDeque deque = new ArrayDeque<>();if(root.left==null && root.right==null){return true;} else if(root.left!=null && root.right!=null){deque.add(root.left);deque.add(root.right);} else {return false;}while (!deque.isEmpty()){TreeNode node1 = deque.pollFirst();TreeNode node2 = deque.pollFirst();if(node2.val!=node1.val || (node1.left!=null && node2.right==null)||(node1.left==null && node2.right!=null)||(node1.right==null && node2.left!=null)||(node1.right!=null && node2.left==null)){return false;}if(node1.left!=null){deque.add(node1.left);deque.add(node2.right);}if(node1.right!=null){deque.add(node1.right);deque.add(node2.left);}}return true;}
      

104. 二叉树的最大深度

public int depth(TreeNode root){if(root==null){return 0 ;}int leftDepth = depth(root.left);int rightDepth = depth(root.right);return Math.max(leftDepth,rightDepth)+1;}public int maxDepth(TreeNode root) {//两种方法 ,一种是递归法,一种是层次遍历法// 递归法//return depth(root);// 层次遍历ArrayDeque deque = new ArrayDeque<>();deque.add(root);int count = 0 ;while (!deque.isEmpty()){int size = deque.size();for (int i = 0; i < size; i++) {TreeNode node = deque.pollFirst();if(node.left!=null){deque.add(node.left);}if(node.right!=null){deque.add(node.right);}}count++;}return count;}

111. 二叉树的最小深度

    public int minDepth(TreeNode root) {//这道题有坑,注意是叶子节点if(root==null){return 0;}if(root.left==null && root.right==null){return 1;}int leftMin = Integer.MAX_VALUE;int rightMin = Integer.MAX_VALUE;if(root.left!=null){leftMin = minDepth(root.left);}if(root.right!=null){rightMin = minDepth(root.right);}return Math.min(leftMin,rightMin)+1;}

110. 平衡二叉树

public int depth(TreeNode root){if(root==null){return  0 ;}int left = depth(root.left);int right = depth(root.right);return Math.max(left,right)+1;}public boolean isBalanced(TreeNode root) {if(root==null){return true;}int leftDepth = depth(root.left);int rightDepth = depth(root.right);if(Math.abs(leftDepth-rightDepth)>1){return false;}else {return isBalanced(root.left) && isBalanced(root.right);}}

路径和问题

257. 二叉树的所有路径

public List binaryTreePaths(TreeNode root) {//路径问题使用深度优先搜索,可以递归实现或者迭代实现// 迭代法:注意路径栈要和节点栈同行ArrayList res = new ArrayList<>();Stack stack = new Stack<>();Stack paths = new Stack<>();stack.add(root);paths.add(root.val+"");while(!stack.isEmpty()){TreeNode node = stack.pop();String path = paths.pop();if(node.left==null && node.right==null){res.add(path);}if(node.right!=null){stack.add(node.right);paths.add(path+"->"+node.right.val);}if(node.left!=null){stack.add(node.left);paths.add(path+"->"+node.left.val);}}return res;}
public void treePath(TreeNode root,ArrayList paths, ArrayList res){paths.add(root.val);if(root.left==null && root.right==null){StringBuffer sb = new StringBuffer();for (int i = 0; i < paths.size() - 1; i++) {sb.append(paths.get(i)+"->");}sb.append(paths.get(paths.size()-1));res.add(sb.toString());return;}if(root.left!=null){treePath(root.left,paths,res);paths.remove(paths.size()-1);}if(root.right!=null){treePath(root.right,paths,res);paths.remove(paths.size()-1);}
}
public List binaryTreePaths(TreeNode root) {//路径问题使用深度优先搜索,可以递归实现或者迭代实现// 递归实现ArrayList res = new ArrayList<>();ArrayList paths = new ArrayList<>();treePath(root,paths,res);return res;
}

如果要得到的是路径是数组而非字符串,可以使用下面的数组替代字符串,不过最大的问题是,注意传进去的是引用,所以需要深拷贝,先拷贝再操作,一定不动原来的数组:

public int pathSum(TreeNode root, int targetSum) {//先得到所有的路径,再前缀和法求解//这次使用迭代法ArrayList> res = new ArrayList<>();Stack stack = new Stack<>();Stack> paths = new Stack<>();stack.add(root);ArrayList f = new ArrayList<>();f.add(root.val);paths.add(f);while (!stack.isEmpty()){TreeNode node = stack.pop();ArrayList path_temp = paths.pop(); ArrayList path = new ArrayList<>(path_temp);if(node.left==null && node.right==null){res.add(new ArrayList<>(path));}if(node.right!=null){stack.add(node.right);//先拷贝再操作ArrayList rightNewPath = new ArrayList<>(path);rightNewPath.add(node.right.val);paths.add(rightNewPath);}if(node.left!=null){stack.add(node.left);//先拷贝再操作ArrayList leftNewPath = new ArrayList<>(path);leftNewPath.add(node.left.val);paths.add(leftNewPath);}} }

112. 路径总和

    boolean res = false;public void dfs(TreeNode root, int target ,ArrayList path){if(root==null){return;}path.add(root.val);if(root.left==null && root.right==null){int sum = 0;for (int a : path){sum+=a;}if(sum==target){res = true;}return;}if(root.right!=null){dfs(root.right,target,path);//注意回溯path.remove(path.size()-1);}if (root.left!=null){dfs(root.left,target,path);//注意回溯path.remove(path.size()-1);}}public boolean hasPathSum(TreeNode root, int targetSum) {// 采用递归法ArrayList path = new ArrayList<>();dfs(root,targetSum,path);return res;}

113. 路径总和 II

     public void dfs(TreeNode root, int target , ArrayList path,List> res){if(root==null){return;}path.add(root.val);if(root.left==null && root.right==null){int sum = 0;ArrayList temp = new ArrayList<>();for (int a : path){sum+=a;temp.add(a);}if(sum==target){res.add(temp);}return;}if(root.right!=null){dfs(root.right,target,path,res);//注意回溯path.remove(path.size()-1);}if (root.left!=null){dfs(root.left,target,path,res);//注意回溯path.remove(path.size()-1);}}public List> pathSum(TreeNode root, int targetSum) {// 采用递归法ArrayList path = new ArrayList<>();List> res = new ArrayList<>();dfs(root,targetSum,path,res);return res;}

654. 最大二叉树

public TreeNode buildTree(int[] nums, int left, int right) {if (left > right) {return null;}int maxIdx = left;for (int i = left; i <= right; i++) {if (nums[i] > nums[maxIdx]) {maxIdx = i;}}TreeNode root = new TreeNode(nums[maxIdx] );root.left = buildTree(nums, left, maxIdx - 1);root.right = buildTree(nums, maxIdx + 1, right);return root;}public TreeNode constructMaximumBinaryTree(int[] nums) {//递归法TreeNode root = buildTree(nums, 0, nums.length - 1);return root;}

617. 合并二叉树

public TreeNode mergeTrees(TreeNode root1, TreeNode root2) {if(root1==null && root2==null){return null;}if(root1==null){return root2;}if(root2==null){return root1;}TreeNode root = new TreeNode(root1.val + root2.val);root.left = mergeTrees(root1.left,root2.left);root.right = mergeTrees(root1.right,root2.right);return root;}

98. 验证二叉搜索树

class Solution {long prevalue = Long.MIN_VALUE;public boolean isValidBST(TreeNode root) {//要知道中序遍历下,输出的二叉搜索树节点的数值是有序序列。//有了这个特性,验证二叉搜索树,就相当于变成了判断一个序列是不是递增的了if(root==null){return true;}if(!isValidBST(root.left)){return false;}if(root.val<=prevalue){return false;}prevalue = (long)root.val;if(!isValidBST(root.right)){return false;}return true;}
}

236. 二叉树的最近公共祖先

public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {if(root==null || root.val==p.val || root.val==q.val){return root;}TreeNode left = lowestCommonAncestor(root.left,p,q);TreeNode right = lowestCommonAncestor(root.right,p,q);if(left!=null && right!=null){return root;}if(left==null && right!=null){return right;}if(left!=null && right==null){return left;}return null;}

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

public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {if(root==null || p.val==root.val || q.val==root.val){return root;}if(p.val > root.val && q.valreturn root;}if(p.val < root.val && q.val > root.val){return root;}if(p.val > root.val && q.val>root.val){return lowestCommonAncestor(root.right,p,q);}if(p.valreturn lowestCommonAncestor(root.left,p,q);}return null;}

701. 二叉搜索树中的插入操作

public TreeNode insertIntoBST(TreeNode root, int val) {if(root==null){root = new TreeNode(val);return root;}if(root!=null && root.left==null && root.val>=val){root.left = new TreeNode(val);}if(root!=null && root.right==null && root.valroot.right = new TreeNode(val);}if(val<=root.val){insertIntoBST(root.left,val);}else {insertIntoBST(root.right,val);}return root;}

108. 将有序数组转换为二叉搜索树

    public TreeNode buildTree(int[] nums,int left,int right){if(left>right){return null;}int mid = (left+right)/2;TreeNode root = new TreeNode(nums[mid]);root.left = buildTree(nums,left,mid-1);root.right = buildTree(nums,mid+1,right);return root;}public TreeNode sortedArrayToBST(int[] nums) {return buildTree(nums,0,nums.length-1);}

538. 把二叉搜索树转换为累加树

public class lc538 {int preNode = 0;public void dfs(TreeNode root ){// 遍历顺序:右中左if(root==null){return ;}if(root.right!=null){dfs(root.right);}preNode += root.val;root.val = preNode;if(root.left!=null){dfs(root.left );}}public TreeNode convertBST(TreeNode root) {dfs(root);return root;}
}

相关内容

热门资讯

基于ggdensity包的等高... 简介 科研过程中,需要绘制某个后验密度/其他的形状。在发表论文中常常使用等高线来满足该...
Leetcode 105. 从... 题目: 给定两个整数数组 preorder 和 inorder ,其中 ...
点亮LED 目录 一、LED 硬件控制方式 二、LED 应用程序 1、定义宏 2、main函数 ①、打开文件  ...
随想008:烂摊子 我看到过很多离谱的现象。比如: 程序 代码重复、命名随意、逻辑混乱、甚至对齐都不一致&...
2023长沙到广州的火车时刻表... 今天给各位分享2023长沙到广州的火车时刻表,从长沙到广州高铁最新...的知识,其中也会对长沙到广州...
车载DVD一体机导航升级教程(... 本篇文章极速百科给大家谈谈车载DVD一体机导航升级教程(凯立德)(超详细),以及汽车凯立德导航用u盘...
圈内sp是什么意思(sp圈里是... 今天给各位分享圈内sp是什么意思的知识,其中也会对sp圈里是什么样的进行解释,如果能碰巧解决你现在面...
鸡蛋撞地球(鸡蛋撞地球怎么制作... 本篇文章极速百科给大家谈谈鸡蛋撞地球,以及鸡蛋撞地球怎么制作对应的知识点,希望对各位有所帮助,不要忘...
Vue2基础语法速通2 目录计算属性计算属性的简写监视属性深层次监视watch 和 computed 区别绑定 class ...
2023年全国最新高校辅导员精... 百分百题库提供高校辅导员考试试题、辅导员考试预测题、高校辅导员考试真题、辅导员证考试题库等ÿ...
Web前端:Angular和R...   在编程领域,Angular 和 React 对于前端开发人员来说是目前最流行的两款...
【Git】SourceTree... 本系列文章前言   之前一直用的TeamFoundation,近期要代码迁移到Gite...
五官是指哪些(五官是指哪些器官... 今天给各位分享五官是指哪些的知识,其中也会对五官是指哪些器官进行解释,如果能碰巧解决你现在面临的问题...
北京汽车交易市场有哪些(北京车... 本篇文章极速百科给大家谈谈北京汽车交易市场有哪些,以及北京车市场在哪里对应的知识点,希望对各位有所帮...
微信吃喝玩乐在哪里搜(微信中吃... 本篇文章极速百科给大家谈谈微信吃喝玩乐在哪里搜,以及微信中吃喝玩乐在哪儿对应的知识点,希望对各位有所...
马勒滤清器怎么样(马勒滤清器产... 今天给各位分享马勒滤清器怎么样的知识,其中也会对马勒滤清器产品目录进行解释,如果能碰巧解决你现在面临...
Java服务器-NIO模型-J... Java服务器 NIO概览 NIO模型 每个客户端关联的套接字都注册到服务器的选择器(...
Vault配置中心产品调研实施... Vault配置中心产品调研实施方案 一、需求描述 nacos作为配置中文,数据都是明文...
镜头校正软件的新标杆DxO P... 镜头校正软件的新标杆DxO PhotoLab 6 的光学校正功能基于 DxO 专用实验室 20 年的...
CNI 网络流量 5.2 Ci... 文章目录Pod 间同节点 pod跨节点 pod in vxlan小结 环境: fedo...
汽车养护,汽车养护品牌排行榜前... 今天给各位分享汽车养护,汽车养护品牌排行榜前十名的知识,其中也会对汽车养护产品品牌进行解释,如果能碰...
大灯随动转向是什么意思?随动转... 今天给各位分享大灯随动转向是什么意思?随动转向大灯是什么功能的知识,其中也会对大灯随动转向是近光还是...
80厘米是几尺几寸(78厘米是... 本篇文章极速百科给大家谈谈80厘米是几尺几寸,以及78厘米是几尺几寸对应的知识点,希望对各位有所帮助...
拉杆旅行箱包十大品牌排行(拉杆... 今天给各位分享拉杆旅行箱包十大品牌排行的知识,其中也会对拉杆旅行包价格进行解释,如果能碰巧解决你现在...
Vue2学习小笔记(一篇带你入... 一篇入门Vue2一、基础概念1.1 MVC和MVVM1.2 初识Vue1.2.1 Vue是什么1.2...
【3.17】MySQL索引整理... 3.1 索引常见面试题 索引的分类 什么是索引? 索引是一种数据结构,...
ASEMI代理PCF85163... 编辑:ll ASEMI代理PCF85163T/1,518原装NXP车规级PCF8516...
83、NeRFshop: In... 简介 主页:https://repo-sam.inria.fr/fungraph/ne...
车辆违章查询电话是多少(车辆违... 本篇文章极速百科给大家谈谈车辆违章查询电话是多少,以及车辆违章查询客服电话是多少对应的知识点,希望对...
5寸照片是多大尺寸(5寸照片是... 本篇文章极速百科给大家谈谈5寸照片是多大尺寸,以及5寸照片是多大尺寸的对应的知识点,希望对各位有所帮...