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 ...
随机推荐
- pxe+kickstart自动化批量安装系统详解-技术流ken
前言 pxe+kickstart是一款可以实现自动化批量安装系统的服务,比较经典,下面将详细介绍此服务的安装和使用. 系统环境准备 系统版本:CentOS release 6.7 (Final) 内网 ...
- Google Maps API Key申请办法(最新)
之前的Google Maps Api的API Key很容易申请,只需要按照一个简单的表单提交部署的网站地址即可,自动生成API Key并给出引用的路径. 但是最近在处理另外一个项目的时候发现之前的这种 ...
- git获取远程服务器的指定分支
昨天糗大了...进入新公司,公司服务器上有Online为线上版本,开发版本默认的为Master,本地clone的开发版为master,公司用的git 自动部署(puh后服务器自动更新了代码...这个有 ...
- 全网最贴心webpack系列教程和配套代码
webpack-demos:全网最贴心 webpack 系列教程和配套代码 欢迎关注个人技术博客:godbmw.com.每周 1 篇原创技术分享!开源教程(webpack.设计模式).面试刷题(偏前端 ...
- Android Service解析
Android Service是一个可以在后台执行长时间运行操作而不提供用户界面的应用组件,它分为两种工作状态,一种是启动状态,主要用于执行后台计算:另一种是绑定状态,主要用于其他组件和Service ...
- 前端常见算法的JS实现
1.冒泡排序 function bubbleSort(arr){ var i = 0, j = 0; for(i=1; i<arr.length; i++){ for(j=0; j<=ar ...
- css:Media Queries: How to target desktop, tablet and mobile?
<!doctype html> <html> <head> <meta name="viewport" content="wid ...
- vue单页应用添加百度统计
前言 申请百度统计后,会得到一段JS代码,需要插入到每个网页中去,在Vue.js项目首先想到的可能就是,把统计代码插入到index.html入口文件中,这样就全局插入,每个页面就都有了;这样做就涉及到 ...
- JS之console.log详解以及兄弟姐们邻居方法扩展
console.log() 基本用法 console.log,前端常用它来调试分析代码,你可以在任何的js代码中调用console.log(),然后你就可以在浏览器控制台看到你刚才打印的常量,变量,数 ...
- springboot 数据验证
不能相信前端传过来的任何数据 一定不能相信前端传过来的任何数据 绝对不能相信前端传过来的任何数据 @JsonFormat 时间必须是指定的格式(这里是接收参数格式,不是取数据来格式化) @Null 必 ...