Day60:把二叉树打印成多行

时间:2022-07-24
本文章向大家介绍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] 负雪明烛