剑指offer第32题 从上到下打印二叉树

问题1:从上到下打印

问题描述:

从上到下打印出二叉树的每个节点,同一层的节点按照从左到右的顺序打印。

例如:
给定二叉树: [3,9,20,null,null,15,7]

    3
   / \
  9  20
    /  \
   15   7

返回:

[3,9,20,15,7]

解题思路:

  本题考查的是树的层次遍历,使用广度搜索(BFS)即可解决。创建一个队列,首先将根节点压入队列,然后循环取出队列中的节点进行遍历,将节点的值放入结果集中,并将该节点的左右子树分别压入队列中;需要注意的是压入队列的时候判断一下节点是否为空;防止出现空指针异常。
  特殊值的处理,当传入的根节点为空时,返回一个空数组。

代码实现:


import java.util.ArrayList;
import java.util.*;

public class t32从上到下打印二叉树 {
    public int[] levelOrder(TreeNode root) {
    	if(root==null) return new int[0];
    	ArrayList<Integer> res = new ArrayList<Integer>();
    	Queue<TreeNode> list = new LinkedList<TreeNode>();  //用于广度搜索的队列
    	list.add(root);
    	while(!list.isEmpty()) {
    		TreeNode temp = list.poll();   //取出队列中的元素
			res.add(temp.val); 
			if(temp.left!=null) //防止空指针异常
				list.add(temp.left);  //将左子树压入队列
			if(temp.right!=null)
				list.add(temp.right); //将右子树压入队列
    	}
    	
    	//将list转换为数组
    	int[] arr = new int[res.size()];
    	int i = 0;
    	for(Integer num: res) {
    		arr[i++] = num;
    	}
    	return arr;
    }
}

算法复杂度分析:

  • 时间复杂度为:O(N);N 为二叉树的节点数量,即 BFS 需循环 N 次。
  • 空间复杂度为:O(N);最差情况下,即当树为平衡二叉树时,最多有 N/2 个树节点同时在 队列中,使用 O(N) 大小的额外空间。

提交结果:
在这里插入图片描述



问题2:一层一行打印

问题描述:

从上到下按层打印二叉树,同一层的节点按从左到右的顺序打印,每一层打印到一行。

例如:
给定二叉树: [3,9,20,null,null,15,7],

    3
   / \
  9  20
    /  \
   15   7

返回其层次遍历结果:

[
  [3],
  [9,20],
  [15,7]
]

解题思路:

  这题的解题思路和上一题的差不多,也是用广度搜索(BFS),需要注意的是怎么样分层;其实在每一次进入循环的时候队列中剩余的节点就是上一层中的所有节点。所以在进入循环的时候我们获取队列的大小作为内部循环的次数即可。

代码实现:

import java.util.LinkedList;
import java.util.List;
import java.util.Queue;

public class t32分层打印二叉树 {
    public List<List<Integer>> levelOrder(TreeNode root) {
    	LinkedList<List<Integer>> res = new LinkedList<List<Integer>>(); 
    	Queue<TreeNode> queue = new LinkedList<TreeNode>();
    	if(root!=null) {
    		queue.add(root);
    	}else {
    		return res;
    	}
    	while(!queue.isEmpty()) {
    		List<Integer> temp = new LinkedList<Integer>();
    		//当前队列中剩余的节点就是上一层中的所有节点
    		for(int i=queue.size(); i>0; i--) {
    			TreeNode t = queue.poll();
    			temp.add(t.val);
    			if(t.left!=null)
    				queue.add(t.left);
    			if(t.right!=null)
    				queue.add(t.right);
    		}
    		res.add(temp);
    	}
    	return res;
    }
}

算法复杂度分析:

  • 时间复杂度为:O(N);N 为二叉树的节点数量,即 BFS 需循环 N 次。
  • 空间复杂度为:O(N);最差情况下,即当树为平衡二叉树时,最多有 N/2 个树节点同时在 队列中,使用 O(N) 大小的额外空间。

提交结果:
在这里插入图片描述



问题3:之字形打印二叉树

问题描述:

请实现一个函数按照之字形顺序打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右到左的顺序打印,第三行再按照从左到右的顺序打印,其他行以此类推。

例如:
给定二叉树: [3,9,20,null,null,15,7],

    3
   / \
  9  20
    /  \
   15   7

返回其层次遍历结果:

[
  [3],
  [20,9],
  [15,7]
]

解题思路:

  这题和上一题相比,需要注意的是存放的顺序,创建一个标志符用于控制每一行的存放顺序即可。这里需要注意的是不能通过节点加入队列的顺序去控制每一层打印的顺序,因为加入队列的顺序是层层影响的。
  所以我们用存放进链表中的顺序来控制,一层从链表的头部开始添加元素,下一层就从链表的尾部开始添加元素。从而达到之字形打印的效果。

错误的案例: 通过节点加入队列的顺序去控制每一层打印的顺序,如下:

  public List<List<Integer>> levelOrder(TreeNode root) {
        LinkedList<List<Integer>> res = new LinkedList<List<Integer>>(); 
    	Queue<TreeNode> queue = new LinkedList<TreeNode>();
    	boolean flag = false;
    	if(root!=null) {
    		queue.add(root);
    	}else {
    		return res;
    	}
    	while(!queue.isEmpty()) {
    		List<Integer> temp = new LinkedList<Integer>();
    		//当前队列中剩余的节点就是上一层中的所有节点
    		for(int i=queue.size(); i>0; i--) {
    			TreeNode t = queue.poll();
    			temp.add(t.val);
    			if(flag) {
    				if(t.left!=null)
    					queue.add(t.left);
    				if(t.right!=null)
    					queue.add(t.right);
    			}else {
    				if(t.right!=null)
    					queue.add(t.right);
    				if(t.left!=null)
    					queue.add(t.left);
    			}
    		}
    		flag = !flag;   //改变顺序
    		res.add(temp);
    	}
    	return res;
    }

代码实现:

import java.util.LinkedList;
import java.util.List;
import java.util.Queue;

public class t32之字形分层打印二叉树 {
    public List<List<Integer>> levelOrder(TreeNode root) {
    	LinkedList<List<Integer>> res = new LinkedList<List<Integer>>(); 
    	Queue<TreeNode> queue = new LinkedList<TreeNode>();
    	boolean flag = false;   //用于控制存放的方向,
    	if(root!=null) {
    		queue.add(root);
    	}else {
    		return res;
    	}
    	while(!queue.isEmpty()) {
    		LinkedList<Integer> temp = new LinkedList<Integer>();
    		//当前队列中剩余的节点就是上一层中的所有节点
    		for(int i=queue.size(); i>0; i--) {
    			TreeNode t = queue.poll();
    			if(flag) {
    				temp.addFirst(t.val);  //添加在头部
    			}else {
    				temp.add(t.val);   //添加在尾部
    			}
    			if(t.left!=null)
    				queue.add(t.left);
    			if(t.right!=null)
    				queue.add(t.right);
    		}
    		flag = !flag;   //改变顺序
    		res.add(temp);
    	}
    	return res;
    }
}

算法复杂度分析:

  • 时间复杂度为:O(N);N 为二叉树的节点数量,即 BFS 需循环 N 次。
  • 空间复杂度为:O(N);最差情况下,即当树为平衡二叉树时,最多有 N/2 个树节点同时在 队列中,使用 O(N) 大小的额外空间。
  • 和上一题相比,每一次多了一个条件判断。

提交结果:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

逍遥自在”

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值