LeetCode算法题-Binary Tree Level Order Traversal II(Java实现)
这是悦乐书的第165次更新,第167篇原创
01 看题和准备
今天介绍的是LeetCode算法题中Easy级别的第24题(顺位题号是107)。给定二叉树,返回其节点值的自下而上级别顺序遍历(即从左到右,逐层逐层)。例如:
给定二叉树[3,9,20,null,null,15,7],
3
/ \
9 20
/ \
15 7
返回其自下而上的级别顺序遍历:[[15,7],[9,20],[3]]。
本次解题使用的开发工具是eclipse,jdk使用的版本是1.8,环境是win7 64位系统,使用Java语言编写和测试。
02 第一种解法
特殊情况:当传入的二叉树为空时,返回我们新定义的空List即可。
正常情况:从示例最后要求输出的结果来看,根节点是数组的最后一位元素,如果是自顶向下遍历节点,我们可以使用队列,借助其先进先出的特点,一层一层遍历节点,将每一层遍历的节点值存入List中,再将List放入List2中,最后再倒序遍历List2存入List3中,List3就是最后的结果。
public List<List<Integer>> levelOrderBottom(TreeNode root) {
List<List<Integer>> list2 = new ArrayList<>();
if (root == null) {
return list2;
}
List<Integer> list = new ArrayList<Integer>();
Queue<TreeNode> q = new LinkedList<>();
q.add(root);
while (!q.isEmpty()) {
list = new ArrayList<Integer>();
Queue<TreeNode> tem = new LinkedList<>();
while (!q.isEmpty()) {
TreeNode t = q.poll();
list.add(t.val);
if (t.left != null) {
tem.add(t.left);
}
if (t.right != null) {
tem.add(t.right);
}
}
list2.add(list);
q = tem;
}
List<List<Integer>> list3 = new ArrayList<>();
for(int i=list2.size()-1; i >= 0; i--){
list3.add(list2.get(i));
}
return list3;
}
遍历节点的处理方法和昨天那道求最长路径的写法类似,借助队列先进先出的特点,从左往右依次循环。
03 第二种解法
我们可以将第一种解法再优化下,不再创建新的队列来存新的一层的节点。和昨天那道题的写法类似,借助队列的size来作为判断条件。
public List<List<Integer>> levelOrderBottom2(TreeNode root) {
List<List<Integer>> list2 = new ArrayList<>();
if (root == null) {
return list2;
}
List<Integer> list = new ArrayList<Integer>();
Queue<TreeNode> q = new LinkedList<>();
q.offer(root);
while (!q.isEmpty()) {
list = new ArrayList<Integer>();
int n = q.size();
while (n-- > 0) {
TreeNode t = q.poll();
list.add(t.val);
if (t.left != null) {
q.offer(t.left);
}
if (t.right != null) {
q.offer(t.right);
}
}
list2.add(list);
}
List<List<Integer>> list3 = new ArrayList<>();
for(int i=list2.size()-1; i >= 0; i--){
list3.add(list2.get(i));
}
return list3;
}
04 第三种解法
上面两种解法都是使用新的List来存储List2倒序遍历的值作为最后结果返回,既然是先进后出的特点,我们可以使用栈来存储每遍历一层节点存入的List,再使用栈的pop方法出栈存入新的List。
public List<List<Integer>> levelOrderBottom3(TreeNode root) {
List<List<Integer>> list2 = new ArrayList<>();
if (root == null) {
return list2;
}
List<Integer> list = new ArrayList<Integer>();
Stack<List<Integer>> stack = new Stack<List<Integer>>();
Queue<TreeNode> q = new LinkedList<>();
q.offer(root);
while (!q.isEmpty()) {
list = new ArrayList<Integer>();
int n = q.size();
while (n-- > 0) {
TreeNode t = q.poll();
list.add(t.val);
if (t.left != null) {
q.offer(t.left);
}
if (t.right != null) {
q.offer(t.right);
}
}
stack.add(list);
}
while (!stack.isEmpty()) {
list2.add(stack.pop());
}
return list2;
}
05 第四种解法
上面的三种都是使用遍历的方式,那我们可不可以使用递归的方法遍历每一层的节点值?显然是可以的,我们可以使用层数作为标记,来判断现阶段处于那一层,从而来决定是新建一个List还是取已存在的List往里面存入新的节点值。
public List<List<Integer>> levelOrderBottom4(TreeNode root) {
List<List<Integer>> res = new ArrayList<List<Integer>>();
List<List<Integer>> node = new ArrayList<List<Integer>>();
viewTree(root, res, 0);
for (int i=res.size()-1; i>=0; i--) {
node.add(res.get(i));
}
return node;
}
public void viewTree(TreeNode root, List<List<Integer>> res, int deep) {
if(root == null)
return;
if (res.size() <= deep) {
List<Integer> node = new ArrayList<Integer>();
node.add(root.val);
res.add(node);
} else {
List<Integer> node = (List<Integer>)res.get(deep);
node.add(root.val);
}
viewTree(root.left, res, deep+1);
viewTree(root.right, res, deep+1);
}
从根节点开始,先递归获取根节点左子节点及其子节点的节点值,然后再递归获取根节点右子节点及其子节点的节点值。
06 验证与测试
对于上面四种解法,我们选取了一个四层的二叉树来作为测试数据,测试代码如下:
public static void main(String[] args) {
Easy_107_BinaryTreeLevelOrderTraversalII instance = new Easy_107_BinaryTreeLevelOrderTraversalII();
TreeNode t = new TreeNode(1);
TreeNode t2 = new TreeNode(2);
TreeNode t3 = new TreeNode(3);
TreeNode t4 = new TreeNode(4);
TreeNode t5 = new TreeNode(5);
TreeNode t6 = new TreeNode(6);
TreeNode t7 = new TreeNode(7);
TreeNode t8 = new TreeNode(8);
t.left = t2;
t.right = t3;
t2.left = t4;
t2.right = t5;
t3.left = t6;
t3.right = t7;
t7.left = t8;
long start = System.nanoTime();
List<List<Integer>> result = instance.levelOrderBottom(t);
long end = System.nanoTime();
System.out.println("levelOrderBottom---输出:"+result.toString()+" , 用时:"+(end-start)/1000+"微秒");
long start2 = System.nanoTime();
List<List<Integer>> result2 = instance.levelOrderBottom2(t);
long end2 = System.nanoTime();
System.out.println("levelOrderBottom2---输出:"+result2.toString()+" , 用时:"+(end2-start2)/1000+"微秒");
long start3 = System.nanoTime();
List<List<Integer>> result3 = instance.levelOrderBottom3(t);
long end3 = System.nanoTime();
System.out.println("levelOrderBottom3---输出:"+result3.toString()+" , 用时:"+(end3-start3)/1000+"微秒");
long start4 = System.nanoTime();
List<List<Integer>> result4 = instance.levelOrderBottom4(t);
long end4 = System.nanoTime();
System.out.println("levelOrderBottom4---输出:"+result4.toString()+" , 用时:"+(end4-start4)/1000+"微秒");
}
测试结果如下:
levelOrderBottom---输出:[[8], [4, 5, 6, 7], [2, 3], [1]] , 用时:446微秒
levelOrderBottom2---输出:[[8], [4, 5, 6, 7], [2, 3], [1]] , 用时:24微秒
levelOrderBottom3---输出:[[8], [4, 5, 6, 7], [2, 3], [1]] , 用时:55微秒
levelOrderBottom4---输出:[[8], [4, 5, 6, 7], [2, 3], [1]] , 用时:23微秒
因为只是采用单一数据测试,样本数量过少,无法得出太过准确的结论,但还是可以明显看出解法二和解法四其他条件一样的情况下用时是最少的。
07 小结
以上就是全部内容,如果大家有什么好的解法思路、建议或者其他问题,可以下方留言交流,点赞、留言、转发就是对我最大的回报和支持!
LeetCode算法题-Binary Tree Level Order Traversal II(Java实现)的更多相关文章
- LeetCode算法题-N-ary Tree Level Order Traversal(Java实现)
这是悦乐书的第225次更新,第238篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第92题(顺位题号是429).给定n-ary树,返回其节点值的级别顺序遍历.(即,从左到 ...
- 【一天一道LeetCode】#107. Binary Tree Level Order Traversal II
一天一道LeetCode 本系列文章已全部上传至我的github,地址:ZeeCoder's Github 欢迎大家关注我的新浪微博,我的新浪微博 欢迎转载,转载请注明出处 (一)题目 来源: htt ...
- 【LeetCode】107. Binary Tree Level Order Traversal II (2 solutions)
Binary Tree Level Order Traversal II Given a binary tree, return the bottom-up level order traversal ...
- leetcode 107 Binary Tree Level Order Traversal II ----- java
Given a binary tree, return the bottom-up level order traversal of its nodes' values. (ie, from left ...
- 【LeetCode】107. Binary Tree Level Order Traversal II 解题报告 (Python&C++)
作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 方法一:DFS 方法二:迭代 日期 [LeetCode ...
- 【LeetCode】107 - Binary Tree Level Order Traversal II
Given a binary tree, return the bottom-up level order traversal of its nodes' values. (ie, from left ...
- LeetCode OJ 107. Binary Tree Level Order Traversal II
Given a binary tree, return the bottom-up level order traversal of its nodes' values. (ie, from left ...
- LeetCode OJ:Binary Tree Level Order Traversal II(二叉树的层序遍历)
Given a binary tree, return the bottom-up level order traversal of its nodes' values. (ie, from left ...
- 【LeetCode OJ】Binary Tree Level Order Traversal II
Problem Link: https://oj.leetcode.com/problems/binary-tree-level-order-traversal-ii/ Use BFS from th ...
随机推荐
- 详细介绍MySQL/MariaDB的锁
官方手册:https://dev.mysql.com/doc/refman/5.7/en/innodb-locking-transaction-model.html 1.事务提交的方式 在MariaD ...
- 学会这个删库再也不用跑路了~ --技术流ken
前言 相信每一个学IT的人或多或少都听说过从删库到跑路这个梗~下图也是在各种交流群屡禁不止,新人听着也是瑟瑟发抖. 人们茶余饭后,街头巷角难免要问... 下面技术流ken就教给各位新手们一招删库再也不 ...
- 分布式系统监视zabbix讲解十一之zabbix升级--技术流ken
思考 现在有这样一个需求,业务场景想要使用的监控模版没有3.0版本的,只有2.0,我们都知道2.0的模版无法导入进3.0版本的zabbix中,这个时候应该怎么获得3.0的监控模版哪?本篇博客将详细演示 ...
- websocket 初识
websocket 初识 前言 其实很早就知道了 websocket 这个概念了,像现在大火的直播等使用的就是 websocket.之前找爬虫工作,对面问我爬过 websocket 网站没,很汗颜,那 ...
- Spark内存管理机制
Spark内存管理机制 Spark 作为一个基于内存的分布式计算引擎,其内存管理模块在整个系统中扮演着非常重要的角色.理解 Spark 内存管理的基本原理,有助于更好地开发 Spark 应用程序和进行 ...
- C#基础知识总结(四)
摘要 循环结构的总结.跳转语句(break.continue).调试程序 一.循环结构的总结 1.while循环 ; ) { Console.WriteLine(i); i++; } 2.do-whi ...
- 利用OpenCV给图像添加中文标注
利用OpenCV给图像添加中文标注 : 参考:http://blog.sina.com.cn/s/blog_6bbd2dd101012dbh.html 和https://blog.csdn.net/ ...
- Asp.net 获取访问者IP
using System.Web; namespace Wxlhjcyy.Public { public class GetIp { public static string IPAddress { ...
- Laravel篇二之本地版本库关联github
以往的工作中都是使用svn作为版本控制,对git分布式的有些陌生,本篇主要记录的本地存储myWeb-laravel的git版本库与github建立关联. 1.首先进入本地myWeb-laravel,执 ...
- yarn 命令
使用yarn的优点,简而言之就是:锁定版本,下载之前检查完整性. yarn install //安装依赖 yarn upgrade //更新 yarn upgrade immutable //更新指定 ...