Day59:按之字形顺序打印二叉树
剑指Offer_编程题——按之字形顺序打印二叉树
题目描述:
请实现一个函数按照之字形打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右至左的顺序打印,第三行按照从左到右的顺序打印,其他行以此类推。
具体要求:
时间限制: C/C++ 1秒,其他语言2秒 空间限制: C/C++32M,其他语言64M
具体实现:
这道题在之前的题目中遇到过类似的,前面的一道题是从上往下打印二叉树和这道题很类似,只不过那道题是简单的从上到下打印二叉树,而我们这道题在此基础上进行了升华,不仅要打印出二叉树的节点,还要呈之字形打印,当时我们还做了这方面的扩展,详细的可以查看此文章。有了前一道题的基础,我们可以通过多种方法进行实现。 思路一: 正如上面说的,我们前面做过类似的题,我们可以效仿前面的方法。首先我们给定一颗二叉树。如图所示:
这道题需要我们输出的是[[1], [3,2], [4,5,6,7]]。这道题不仅要求按序输出节点值,还要求包含以下信息: 1. 每一层所包含的树节点; 2. 偶数层的树节点需倒序。 我们同样可以与上一道题一样,利用列表存储节点,但不同的是列表每次只存储一层的节点,在遍历当前层节点的同时,存储下一层的节点,以此类推。我们可以用python将其实现:
class Solution:
def Print(self, pRoot):
resultArray = []
if not pRoot:
return resultArray
curLayerNodes = [pRoot]
isEvenLayer = True
while curLayerNodes:
curLayerValues = []
nextLayerNodes = []
isEvenLayer = not isEvenLayer
for node in curLayerNodes:
curLayerValues.append(node.val)
if node.left:
nextLayerNodes.append(node.left)
if node.right:
nextLayerNodes.append(node.right)
curLayerNodes = nextLayerNodes
resultArray.append(curLayerValues[::-1]) if isEvenLayer else resultArray.append(curLayerValues)
return resultArray
代码效果图如图所示:
正如前面说的那样,如果在牛客网中,我们可以直接通过,但是如果是本地的编译器,则还需要定义其结点,具体结点的实现定义用python实现如下:
class TreeNode:
def __init__(self, pNode):
self.val = x
self.left = None
self.right = None
思路二: 与思路一及其类似,只不过在面对要求的偶数层倒序获取每一层的节点的值时,我们有另外一种方式:如果是偶数层,则将每个节点的值插入到列表的头部,即实现了获取节点值时如果是偶数层则倒序排列的效果:具体代码用python实现效果如下:
class Solution:
def Print(self, pRoot):
resultArray = []
if not pRoot:
return resultArray
curLayerNodes = [pRoot]
isEvenLayer = True
while curLayerNodes:
curLayerValues = []
nextLayerNodes = []
isEvenLayer = not isEvenLayer
for node in curLayerNodes:
curLayerValues.insert(0, node.val) if isEvenLayer else curLayerValues.append(node.val)
if node.left:
nextLayerNodes.append(node.left)
if node.right:
nextLayerNodes.append(node.right)
curLayerNodes = nextLayerNodes
resultArray.append(curLayerValues)
return resultArray
代码效果图如图所示:
思路三: 除了上述的思路以外,还可以用两个栈来存储将其实现,具体过程如下: 1.使用两个栈来分别存储奇数层节点和偶数层节点。 2.注意两个栈的插入顺序是不同的。 3.对于奇数层来说,也就是从左往右的顺序,先添加左子树,然后添加右子树。对于偶数层,刚好相反,先添加右子树,然后添加左子树。 具体我们用java和python两种编程语言将其实现。 1、首先我们用java将其实现:
import java.util.ArrayList;
import java.util.Stack;
public class Solution{
public ArrayList<ArrayList<Integer>> Print(TreeNode pRoot){
int level = 1;
Stack<TreeNode> s1 = new Stack<>();
s1.push(pRoot);
Stack<TreeNode> s2 = new Stack<>();
ArrayList<ArrayList<Integer>> list = new ArrayList<>();
while(!s1.empty() || !s2.empty()){
if(level % 2 != 0){
ArrayList<Integer> temp = new ArrayList<>();
while(!s1.empty()){
TreeNode node = s1.pop();
if(node != null){
temp.add(node.val);
s2.push(node.left);
s2.push(node.right);
}
}
if(!temp.isEmpty()){
list.add(temp);
level++;
}
}else{
ArrayList<Integer> temp = new ArrayList<>();
while(! s2.empty()){
TreeNode node = s2.pop();
if(node != null){
temp.add(node.val);
s1.push(node.right);
s1.push(node.left);
}
}
if(!temp.isEmpty()){
list.add(temp);
level++;
}
}
}
return list;
}
}
代码效果图如图所示:
但是在本地编译器中我们还需要定义链表结构才能正常运行,具体用java定义链表结构实现如下:
public class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null;
TreeNode next = null;
TreeNode(int val) {
this.val = val;
}
}
2、接下来我们用python将其思路实现:
class Solution:
def Print(self, pRoot):
res = []
if pRoot == None:
return []
stack = []
stack.append(pRoot)
flag = -1
while stack:
lsStack = []
for i in range(len(stack)):
toor = stack.pop(0)
lsStack.append(toor.val)
if toor.left:
stack.append(toor.left)
if toor.right:
stack.append(toor.right)
if flag == 1:
lsStack = lsStack[::-1]
res.append(lsStack)
flag *= -1
return res
代码效果图如图所示:
思路四: 层序遍历,然后反转。当遍历到奇数层时,从左到右存储该层遍历的值。当遍历到偶数层时,从右到左存储该层遍历的值。接下来我们分别用java和python两种语言将其实现: 1、首先我们用java将其实现:
import java.util.*;
public class Solution{
public ArrayList<ArrayList<Integer>> Print(TreeNode pRoot){
ArrayList<ArrayList<Integer>> result = new ArrayList<>();
if(pRoot == null){
return result;
}
boolean leftToRight = true;
Queue<TreeNode> layer = new LinkedList<>();
ArrayList<Integer> layerList = new ArrayList<>();
layer.add(pRoot);
int start = 0, end = 1;
while(!layer.isEmpty()){
TreeNode cur = layer.remove();
if(leftToRight){
layerList.add(cur.val);
}else{
layerList.add(0, cur.val);
}
start++;
if(cur.left != null){
layer.add(cur.left);
}
if(cur.right != null){
layer.add(cur.right);
}
if(start == end){
end = layer.size();
start = 0;
result.add(layerList);
leftToRight = !leftToRight;
layerList = new ArrayList<Integer>();
}
}
return result;
}
}
代码效果图如图所示:
2、接下来用python将其实现
#层次遍历,然后反转
class Solution:
def Print(self, pRoot):
if not pRoot:
return []
up = [pRoot]
down = []
res = []
while up:
l = []
for i in up:
l.append(i.val)
if i.left:
down.append(i.left)
if i.right:
down.append(i.right)
res.append(l)
up, down = down, []
for j in range(len(res)):
if j % 2 == 1:
res[j] = res[j][::-1]
return res
代码效果图如图所示:
思路五: 将思路四的想法进行升级,其中有一个判断是否偶数我们用的常规方法,这里我们可以将其进行改变,大大提高代码的运行效率,具体用Java实现如下:
import java.util.*;
public class Solution{
public ArrayList<ArrayList<Integer>> Print(TreeNode pRoot){
ArrayList<ArrayList<Integer>> layers = new ArrayList<>();
if (pRoot == null)
return layers;
Deque<TreeNode> queue = new LinkedList<>();
queue.offer(pRoot);
int depth = 0;
while(!queue.isEmpty()){
depth++;
ArrayList<Integer> layer = new ArrayList<>();
int cur = 0, size = queue.size();
if((depth & 1) == 0){
Iterator<TreeNode> it = queue.descendingIterator();
while(it.hasNext()){
layer.add(it.next().val);
}
}
else{
Iterator<TreeNode> it = queue.iterator();
while(it.hasNext()){
layer.add(it.next().val);
}
}
while(cur < size){
TreeNode node = queue.poll();
if(node.left != null){
queue.offer(node.left);
}
if(node.right != null){
queue.offer(node.right);
}
cur++;
}
layers.add(layer);
}
return layers;
}
}
代码效果图如图所示:
思路六: 首先需要我们弄明白的就是,本题需要用到的是栈而不是队列,这点需要我们特别清楚。因此,我们用栈实现这道题,并且,与此同时,设置一个flag,判断是否从左到右压入栈。具体我们用python实现如下:
class Solution:
def Print(self, pRoot):
# write code here
if not pRoot: return []
right_2_left_flag = False
res = []
pCur = [pRoot]
pNext = []
temp = []
while pCur:
node = pCur.pop()
if right_2_left_flag:
if node.right:
pNext.append(node.right)
if node.left:
pNext.append(node.left)
else:
if node.left:
pNext.append(node.left)
if node.right:
pNext.append(node.right)
temp.append(node.val)
if not pCur:
pCur = pNext
pNext = []
right_2_left_flag = not right_2_left_flag
res.append(temp)
temp = []
return res
代码效果图如图所示:
总结
本题主要考察二叉树的遍历以及栈和队列和各种容器的掌握情况。前面有一道题是从上往下打印二叉树与本题考察的内容相似,只不过本题在此基础上进行了延续,要考虑很多的情况。本文给出了六种解题思路,并且分别用java和python两种主要的编程语言将其实现。并且本题的实质再考栈以及各大容器的应用,不能用队列,这点需要我们特别注意。因此,我们在做题的时候,应该多次尝试各种方法,扩展自己的思维,写出优质的代码。总之,我们要继续加油,争取早日找到工作,Good Luck!!!
参考文献
[1] jiangjiane [2] 一个小迷糊66 [3] ouyangyanlan [4] Jack_Kuo
- HDUOJ---(4708)Rotation Lock Puzzle
- HDUOJ---Hamming Distance(4712)
- HDUOJ-----Difference Between Primes
- HDUOJ----(4706)Children's Day
- poj-------Common Subsequence(poj 1458)
- poj----Maximum sum(poj 2479)
- HDUOJ---hello Kiki
- HDUOJ-----X问题
- POJ-----C Looooops
- POJ--Strange Way to Express Integers
- HDUOJ----More is better(并查集)
- HDUOJ 1099——Lottery
- HDUOJ-----取(m堆)石子游戏
- HDUOJ-----Be the Winner
- 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 数组属性和方法
- PHP封装的简单连接MongoDB类示例
- 基于Tensorflow的MNIST手写数字识别分类
- Yii框架ACF(accessController)简单权限控制操作示例
- tensorflow 动态获取 BatchSzie 的大小实例
- TP5.0框架实现无限极回复功能的方法分析
- Tensorflow之MNIST CNN实现并保存、加载模型
- tensorflow 大于某个值为1,小于为0的实例
- YII框架模块化处理操作示例
- 基于tensorflow for循环 while循环案例
- 浅谈Python 命令行参数argparse写入图片路径操作
- 硬核干货丨游戏大世界的超远视距处理手法,建议收藏!
- python实现npy格式文件转换为txt文件操作
- 从0开始打造UI框架:动态化框架Scrollview物理学算法解析
- 基于Keras的格式化输出Loss实现方式
- PHP信号处理机制的操作代码讲解