Day59:按之字形顺序打印二叉树

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