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 ...
随机推荐
- Shuffle过程
Shuffle过程 在MapReduce框架中,shuffle是连接Map和Reduce之间的桥梁,Map的输出要用到Reduce中必须经过shuffle这个环节,shuffle的性能高低直接影响了整 ...
- h5py快速入门指南
h5py是Python语言用来操作HDF5的模块.下面的文章主要介绍h5py的快速入门指南,翻译自h5py的官方文档:http://docs.h5py.org/en/latest/quick.html ...
- Chrome插件开发,美化网页上的文件列表。chrome-extension,background
上一篇文章 通过“content-scripts”的方式向页面注入js和css来美化页面,但是有一个弊端:一旦配置好需要注入的页面,之后如果这个页面地址以后发生变化,或者要新加一些URL进来,那么得修 ...
- ___简单的MVC单个图片上传预览
js: $("#btnImg").click(function () { $("#form0").ajaxSubmit({ url: "/Studen ...
- ubuntu16.4系统和Gentos6.8系统查看开机自启动服务
ubuntu16.4系统查看自启服务: 需要自行安装一个sysv-rc-conf的工具来查看: sudo apt-get install sysv-rc-conf 查看自启命令: sudo sysv- ...
- C# 给一个控件去掉焦点
给一个控件去掉焦点(如选中控件按钮button时,按钮出现方框显示):例如给form这个窗体中的button按钮去焦点1.首先在form这个窗体中拖一个label按钮,去文字,设置背景为透明: 2.然 ...
- ES6之Spread Operater拷贝对象
译者按: 对象拷贝和合并使用展开运算符(Spread Operator)很方便! 原文: Master Javascript’s New, Cutting-Edge Object Spread Ope ...
- 用GitHub Issue取代多说,是不是很厉害?
摘要: 别了,多说,拥抱Gitment. 2017年6月1日,多说正式下线,这多少让人感觉有些遗憾.在比较了多个博客评论系统,我最终选择了Gitment作为本站的博客评论系统: UI简洁,适合我的博客 ...
- thinkphp3.2.3模板渲染支持三元表达式
thinkphp3.2.3模板渲染支持三元表达式 {$status?'正常':'错误'} {$info['status']?$info['msg']:$info['error']} 注意:三元运算符中 ...
- TP5.0 PHPExcel 数据表格导出导入(引)
TP5.0 PHPExcel 数据表格导出导入(引) 今天看的是PHPExcel这个扩展库,Comporse 下载不下来,最后只能自己去github里面手动下载,但有一个问题就是下载下来的PHPExc ...