LeetCode算法之--二叉树系列

news/2024/11/19 9:30:11/

点赞收藏,以防遗忘

本文【程序大视界】已收录,关注免费领取互联网大厂学习资料,添加博主好友进群学习交流,欢迎留言和评论,一起交流共同进步。

【一】前言

二叉树也是面试算法的常见题型,通常程序会自定义树节点,需要我们实现如找出深度、遍历等。

【二】二叉树的最大深度

104. 二叉树的最大深度

给定一个二叉树,找出其最大深度。

二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。

说明: 叶子节点是指没有子节点的节点。

示例:
给定二叉树 [3,9,20,null,null,15,7]

 3/ \9  20/  \15   7

返回它的最大深度 3 。

解法一】深度优先:新建一个result集合用于保存并返回结果集合,边界条件为root为null,则返回result,递归方法开始传入root和levle为0层,依次递增层数并新建结果集合里的子集list,结果集合中添加该节点的值val,并递归遍历该节点的左子树和右子树,直至递归遍历完该二叉树的所有节点,返回的result结果集合就是所求。

class Solution {List<List<Integer>> result = new ArrayList<List<Integer>>();public List<List<Integer>> levelOrder(TreeNode root) {If(root == null){return result ;}dfs(root,0);return result;}public void dfs(TreeNode root,int level){//递归终止条件If(root  == null){return ;} If( result.size == level){result.add(New ArrayList<Integer>());}result.get(level).add(root.val);dfs(root.right,level+1);dfs(root.right,level+1);}
}

解法二】广度优先:新建一个result集合用于保存和返回结果集合,边界条件当root为空,则直接返回结果集。建队列queue保存root根节点,按照每一层左、右子树的顺序,一次访问二叉树的节点,遍历每一层的节点时用一个list集合把该层的所有节点从左到右顺序保存起来,遍历完每一层把list集合添加到结果集合中,遍历完所有层,result结果集合就是要求的答案。

class Solution {public List<List<Integer>> levelOrder(TreeNode root) {List<List<Integer>> result = new ArrayList<List<Integer>>();If(root == null){return result ;}Queue<TreeNode> queue = new LinkedList<TreeNode>();queue.offer(root);While(!queue.isEmpty()){Int size = queue.size();List<Integer> list = new ArrayList<Integer>();While(size >0){TreeNode node = queue.poll();list .add(node.val);If(node.left != null){queue.offer(node.left);}If(node.right != null){queue.offer(node.right);}size --;}result.add(list); }return result ;}
}

【三】二叉树的遍历

94. 二叉树的中序遍历

给定一个二叉树的根节点 root ,返回 它的 中序 遍历 。

示例 1:

输入:root = [1,null,2,3]
输出:[1,3,2]

示例 2:

输入:root = []
输出:[]

示例 3:

输入:root = [1]
输出:[1]

提示:

  • 树中节点数目在范围 [0, 100] 内
  • -100 <= Node.val <= 100

进阶: 递归算法很简单,你可以通过迭代算法完成吗?

【解法一】迭代解决:新建一个List集合用以存放结果返回集合,新建一个Deque双端队列用作遍历二叉树出入栈使用,当root或stack不为空时,遍历二叉树,一直遍历到左子树为空时,从栈弹出节点并把弹出节点的值存入栈中,指针指向弹出节点的右子树节点,继续遍历访问弹出节点右子树节点是否为空,重复该步骤直至遍历完该二叉树为止。

class Solution {public List<Integer> inorderTraversal(TreeNode root) {List<Integer> dataList = new ArrayList<Integer>();Deque<TreeNode> stack = new LinkedList<TreeNode>();While(root != null || !stack.isEmpty()){If(root!= null){stack.push(root);root = root.left;}else{root = stack.pop();dataList.add(root.val);root = root.right;}}return dataList ;}
}

【解法二】递归:递归的解法很简单,递归循环左节点和右节点,递归的终止条件是当root为空时返回。

class Solution {public List<Integer> inorderTraversal(TreeNode root) {List<Integer> dataList = new ArrayList<Integer>();Inorder(root,dataList );return dataList ;}public void inorder(TreeNode root,List<Integer> dataList){If(root == null){return;}inorder(root.left,dataList);dataList.add(root.val);inorder(root.right,dataList);}
}

二叉树的前序遍历

迭代解决】前序遍历的出入栈顺序是:先根节点入栈,根节点出栈,再右节点入栈、左节点入栈,左节点出栈、右节点入栈;如此往复循环直至遍历完整颗二叉树,在每一次出栈时保存节点的值放入list链表,最后得到的list结果集合就是所求结果。

class Solution {public List<Integer> inorderTraversal(TreeNode root) {List<Integer> dataList = new ArrayList<Integer>();Deque<TreeNode> stack = new LinkedList<TreeNode>();stack.push(root); While( !stack.isEmpty()){root = stack.pop();dataList.add(root.val);//先压入右节点,弹出顺序刚好相反If(root.right != null){stack.push(root.right );}//再压入左节点,弹出顺序刚好相反If(root.left!= null){stack.push(root.left);}}return dataList ;}
}

【后序遍历】后序遍历的顺序是:左节点-->右节点-->根  而出栈和入栈的顺序则刚好相反,这题的关键是需要用两个栈结构来解答,一个栈用来遍历,另一个栈用来存储,遍历完第一个栈后,第二个栈出栈遍历的结构就是后续遍历。

class Solution {public List<Integer> inorderTraversal(TreeNode root) {List<Integer> dataList = new ArrayList<Integer>();//第一个栈用来遍历二叉树Deque<TreeNode> stack1 = new LinkedList<TreeNode>();stack1.push(root);//第二个栈用来存放节点最终遍历出栈的顺序就是所要求结果Deque<TreeNode> stack2 = new LinkedList<TreeNode>();While(!stack1.isEmpty()){root = stack1.pop();stack2.push(root.val); If(root.left != null){stack1.push(root.left);}If(root.right != null){stack1.push(root.right);}}while(!stack2.isEmpty()){dataList.add(stack2.pop());}}
}

【四】总结

关于二叉树的解法,常见为深度优先遍历和广度优先遍历,深度优先一般选用递归解法,如求二叉树的深度、层序遍历(节点从左到右顺序)、中序遍历、反转二叉树、对称二叉树等,广度优先采用Queue队列、Deque栈的数据结构来求解,一层一层的遍历按照要求实现具体解法,广度优先也称为迭代解法。

我是程序大视界,坚持原创技术博客分享。

注:如果本篇博客有任何纰漏和建议,欢迎私信或评论留言!

文章持续更新,可以VX搜索「 程序大视界 」第一时间阅读,回复【资料】免费领取学习资料,添加博主VX好友,进群交流获取大厂面试完整考点,欢迎Star。


http://www.ppmy.cn/news/5583.html

相关文章

【数据结构与算法】试卷 1(含答案)

一、选择题 1. 计算机算法指的是&#xff08;&#xff09; A. 计算方法 B. 排序方法 C. 解决问题的有限运算序列 D. 调度方法 2. 表达式 a*(bc)-d 的后缀表达式是&#xff08;&#xff09; A. abcd- B. abc*d- C. abc*d- D. -*abcd 3. 一个栈的入栈序列是a,b,c,d,e&#xff0c;…

卓海科技冲刺创业板:拟募资5.47亿 相宇阳控制52.9%股权

雷递网 雷建平 12月20日无锡卓海科技股份有限公司&#xff08;简称&#xff1a;“卓海科技”&#xff09;日前递交招股书&#xff0c;准备在深交所创业板上市。卓海科技计划募资5.47亿元&#xff0c;其中&#xff0c;1.04亿元用于半导体前道量检测设备扩产项目&#xff0c;1.84…

MyBatis学习 | 全局配置文件

文章目录一、简介二、各个标签2.1 properties&#xff08;属性&#xff09;2.2 settings&#xff08;设置&#xff09;2.3 typeAliases&#xff08;类型命名&#xff09;2.4 typeHandlers&#xff08;类型处理器&#xff09;2.5 plugins&#xff08;插件&#xff09;2.6 enviro…

Exponentiation

Exponentiation is a mathematical operation, written as bn, involving two numbers, the base b and the exponent or power n, and pronounced as “b (raised) to the (power of) n”.[1] When n is a positive integer, exponentiation corresponds to repeated multipli…

四、二维线实体类(AcGeLinearEnt2d)

四、二维线实体类&#xff08;AcGeLinearEnt2d&#xff09; 继承关系&#xff1a;为二维曲线类&#xff08;AcGeCurve2d&#xff09;的派生类&#xff0c;见第一条类图 派生类 直线&#xff1a;AcGeLine2d&#xff0c;对应数据库类型AcDbXline 线段&#xff1a;AcGeLineSeg2d&a…

0基础转软件测试该学些什么?

前言 有很多人员会不断问自己&#xff0c;自己到底要不要学测试&#xff0c;或者要不要转行做测试&#xff0c;测试的职业发展到底怎么样&#xff1f;如果你还在迷茫&#xff0c;在到处找各种大牛问类似的问题&#xff0c;我希望这篇文章&#xff0c;你看完能够结束你的这个烦…

JDBC编程步骤、JDBC API详解和数据库连接池

前言&#xff1a; JDBC 就是使用Java语言操作关系型数据库的一套API &#xff0c;全称&#xff1a;( Java DataBase Connectivity ) Java 数据库连接。官方&#xff08;sun公司&#xff09;定义的一套操作所有关系型数据库的规则&#xff0c;即 接口各个数据库厂商去实现这套…

数据管理篇之数据质量

第15章 数据质量 1.数据质量保障原则 完整性 准确性 一致性 及时性 2.数据质量方法概述 消费场景知晓 &#xff08;1&#xff09;数据资产定义 分为五个等级&#xff1a; ① 毁灭性质&#xff08;A1&#xff09;&#xff0c;数据一旦出错&#xff0c;将会引起重大资产损失&a…