Day60:把二叉树打印成多行
剑指Offer_编程题——把二叉树打印成多行
题目描述:
从上到下按层打印二叉树,同一层结点从左至右输出。每一层输出一行。
具体要求:
时间限制: C/C++ 1秒,其他语言2秒 空间限制: C/C++32M,其他语言64M
具体实现:
这道题在之前的题目中遇到过类似的,一共有两道类似的题目:前面的一道题是从上往下打印二叉树和这道题很类似,只不过那道题是简单的从上到下打印二叉树,另外的一道就是昨天做的之字形打印二叉树;而我们这道题鉴于这两道题之间,比从上往下打印二叉树要稍微难一点,因为要考虑每一层都要打印这个因素,但是又比昨天的之字形打印二叉树简单一点,不需要考察奇偶行的逆序问题。有了前两道题的基础,我们可以通过多种方法进行实现。 思路一: 正如上面说的,我们前面做过类似的题,我们可以效仿前面的方法。首先我们给定一颗二叉树。如图所示:
以上图的二叉树样例来说,需要说明的点是,题目需要的输出是形如[[1], [2,3], [4,5,6,7]]。具体我们可以利用列表存储二叉树每一层的节点,在读取列表中当前层节点的同时,存储下一层的节点以备用,以此类推。接下来我们用python将其实现:
class Solution:
def Print(self, pRoot):
if not pRoot:
return []
resultList = []
curLayer = [pRoot]
while curLayer:
curList = []
nextLayer = []
for node in curLayer:
curList.append(node.val)
if node.left:
nextLayer.append(node.left)
if node.right:
nextLayer.append(node.right)
resultList.append(curList)
curLayer = nextLayer
return resultList
代码效果图如图所示:
正如前面说的那样,如果在牛客网中,我们可以直接通过,但是如果是本地的编译器,则还需要定义其结点,具体结点的实现定义用python实现如下:
class TreeNode:
def __init__(self, pNode):
self.val = x
self.left = None
self.right = None
思路二: 我们昨天在解答用之字形打印二叉树的题目时,利用了栈的“先进后出的特性”,在这里,我们可以利用对列的“先进先出”的特性。首先要知道队列的方法;利用arraylist的方法。总结如下所示:
分层输出的层次遍历和普通的层次遍历类似,用start和end进行分层,一旦达到end就重置start为0,end为当前队列大小,具体我们可以用两种方法实现该思路,接下来我们用java来分别实现: 1、利用ArrayList阻塞机制来模拟队列来实现
import java.util.ArrayList;
public class Solution{
ArrayList<ArrayList<Integer> > Print(TreeNode pRoot){
ArrayList<ArrayList<Integer>> out = new ArrayList<>();
if(pRoot == null)
return out;
ArrayList<TreeNode> queue = new ArrayList<>();
ArrayList<Integer> in = new ArrayList<>();
queue.add(pRoot);
int start = 0;
int end = 1;
while(queue.size() > 0){
TreeNode temp = queue.remove(0);
in.add(temp.val);
start++;
if(temp.left != null)
queue.add(temp.left);
if(temp.right != null)
queue.add(temp.right);
if(start == end){
end = queue.size();
start = 0;
out.add(in);
in = new ArrayList<Integer>();
}
}
return out;
}
}
代码效果图如图所示:
但是在本地编译器中我们还需要定义链表结构才能正常运行,具体用java定义树结构实现如下:
public class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null;
TreeNode next = null;
TreeNode(int val) {
this.val = val;
}
}
2、接下来我们直接用java中的队列来解决该题,用java实现如下:
import java.util.*;
public class Solution{
ArrayList<ArrayList<Integer>> Print(TreeNode pRoot){
ArrayList<ArrayList<Integer>> ret = new ArrayList<>();
Queue<TreeNode> queue = new LinkedList<>();
queue.add(pRoot);
while(!queue.isEmpty()){
ArrayList<Integer> list = new ArrayList<>();
int cnt = queue.size();
while(cnt-- >0){
TreeNode node = queue.poll();
if(node == null)
continue;
list.add(node.val);
queue.add(node.left);
queue.add(node.right);
}
if(list.size() != 0){
ret.add(list);
}
}
return ret;
}
}
代码效果图如图所示:
思路三: 其实是在思路二的基础上进行的改进,也就是本质还是用队列,但是我们加一个计时器,具体计算过程:nextLevel来计算下一层的个数,使用toBeList计算这层还么有打印完的个数;初始nextLevel = 0, toBeList = 1,之后每次放入一个队列,nextLevel+1,每次出一个队列,toBeList-1,直到toBeList为0之后,就说明这层的打印完了,同时下一层已经计数了。接下来我们用python将其实现:
class Solution:
def Print(self, pRoot):
list = []
result = []
results = []
nextLevel = 0
toBeList = 1
if pRoot == None:
return list
list.append(pRoot)
while list != []:
treeNode = list.pop(0)
toBeList -= 1
result.append(treeNode.val)
if treeNode.left:
nextLevel += 1
list.append(treeNode.left)
if treeNode.right:
nextLevel += 1
list.append(treeNode.right)
if toBeList == 0:
results.append(result)
result = []
toBeList = nextLevel
nextLevel = 0
return results
代码效果图如图所示:
思路四: 本题可以使用二叉树常用的递归方法;也就是常用的层次遍历。具体我们可以使用depth表示当前打印的层数。当前节点为空,返回。当前层数 > 已打印的层数,扩容。将元素添加入集合。向左递归、向右递归.我们具体用java和python两种语言将其实现: 1、首先我们用java将其实现:
import java.util.ArrayList;
public class Solution{
ArrayList<ArrayList<Integer> > Print(TreeNode pRoot) {
ArrayList<ArrayList<Integer>> list = new ArrayList<>();
if(pRoot == null) return list;
depth(pRoot,1,list);
return list;
}
private void depth(TreeNode root,int depth,ArrayList<ArrayList<Integer>> list){
if(root == null) return;
if(depth > list.size()){
list.add(new ArrayList<Integer>());
}
list.get(depth-1).add(root.val);
depth(root.left,depth+1,list);
depth(root.right,depth+1,list);
}
}
代码效果图如图所示:
2、接下来用python将其实现:
class Solution:
def Print(self, pRoot):
res = []
self.level(pRoot, 0, res)
return res
def level(self, root, level, res):
if not root:
return
if level == len(res):
res.append([])
res[level].append(root.val)
if root.left:
self.level(root.left, level+1, res)
if root.right:
self.level(root.right, level+1, res)
代码效果图如图所示:
总结
本题主要考察二叉树的层次遍历以及队列和各种容器的掌握情况。前面有两道题与之类似,其中一道题是从上往下打印二叉树与本题考察的内容相似,只不过本题在此基础上进行了延续,要考虑一些情况,还有一道题就是昨天做的之字形打印出二叉树。本文给出了四种解题思路,并且分别用java和python两种主要的编程语言将其实现。并且本题的实质再考栈以及各大容器的应用,这道题可以用队列,也可以用递归。因此,我们在做题的时候,应该多次尝试各种方法,扩展自己的思维,写出优质的代码。总之,我们要继续加油,争取早日找到工作,Good Luck!!!
参考文献
[1] goddaniel [2] IDEA_TEYU_1112 [3] hustfc [4] 一只菜鸡的奋斗史 [5] 负雪明烛
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Struts Scan工具的使用
- 树莓派基础实验24:超声波测距传感器实验
- 数据结构与算法系列2 线性表 链表的分类+使用java实现链表+链表源码详解
- 从spring boot 启动过程看apollo的初始化过程( 二)
- Apache IoTDB 系列教程-4:客户端接口
- 数据结构与算法系列2 线性表 使用java实现动态数组+ArrayList源码详解
- Kali中密码暴力破解工具hydra的使用
- Apache IoTDB 系列教程-8:文件同步工具
- 树莓派基础实验25:DS18B20温度传感器实验
- 迈出加入 Apache IoTDB 社区的第一步!(订阅邮件、调试代码)
- kali下一些代理工具的简单描述
- 树莓派基础实验26:旋转编码器实验
- java web Session会话技术(原理图解+功能+与Cookie的区别+基本使用)
- JAVA创建对象有哪几种方式
- Apache IoTDB 系列教程-7:时序数据文件格式 TsFile