剑指offer32_从上到下打印二叉树_题集

从上到下打印二叉树题集

题目

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

分析

考虑使用队列先进先出的特点;

  • 算法流程:

    • 特例处理: 当树的根节点为空,则直接返回空列表 [] ;
    • 初始化: 打印结果列表 res = [] ,包含根节点的队列 queue = [root] ;* BFS 循环: 当队列 queue 为空时跳出;
      1. 出队: 队首元素出队,记为 node;
      2. 打印: 将 node.val 添加至列表 tmp 尾部;
      3. 添加子节点: 若 node 的左(右)子节点不为空,则将左(右)子节点加入队列 queue ;
    • 返回值: 返回打印结果列表 res 即可。
  • 复杂度:

    • 时间: O(N) : N为树的节点个数,BFS搜说是需要循环N次。
    • 空间: O(N): 最差情况下,即当树为平衡二叉树时,最多有 N/2 个树节点同时在 queue 中,使用 O(N) 大小的额外空间。

code


 // 主要涉及到队列和数组的相关操作还不是很熟~~~

class Solution {
    public int[] levelOrder(TreeNode root) {
        if(root == null) return new int[0];
        Queue<TreeNode> queue = new LinkedList<>(){{ add(root); }}; // LinkedList实现了Queue的接口;
        ArrayList<Integer> ans = new ArrayList<>();
        while(!queue.isEmpty()){
            TreeNode node = queue.poll();
            ans.add(node.val);
            if(node.left != null) queue.offer(node.left);
            if(node.right != null) queue.offer(node.right);
        }
        int[] res = new int[ans.size()];
        for(int i = 0; i < ans.size(); i++){
            res[i] = ans.get(i);
        }
        return res;
    }
}

python

python版本对队列的操作更简单,不用记复杂的函数;

class Solution(object):
    def levelOrder(self, root):
        """
        :type root: TreeNode
        :rtype: List[int]
        """
        if root == None:
            return []
        queue = [root]
        res = []
        # 使用队列保证了先进先出的特性
        while(queue):
            node = queue.pop(0)
            res.append(node.val)
            if(node.left): queue.append(node.left)
            if(node.right): queue.append(node.right)
        return res  

32 - II

题目:

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

分析:

只用考虑将每一层的节点单独的存放在一个数组中。对每一层的节点个数做一个循环就行。

  • java
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public List<List<Integer>> levelOrder(TreeNode root) {
        
        Queue<TreeNode> queue = new LinkedList<>(); // LinkedList实现了Queue的接口;
        
        List<List<Integer>> ans = new ArrayList<>();
        if(root != null)  queue.add(root);
        while(!queue.isEmpty()){
            List<Integer> temp = new ArrayList<>();
            // for(int i = 0; i < queue.size(); i++){   // 倒着来????
            for(int i = queue.size(); i > 0; i--){
                TreeNode node = queue.poll();
                temp.add(node.val);
                if(node.left != null) queue.add(node.left);
                if(node.right != null) queue.add(node.right);
            }
            ans.add(temp);
        }
        return ans;
    }
}
  • python
class Solution(object):
    def levelOrder(self, root):
        """
        :type root: TreeNode
        :rtype: List[List[int]]
        """
        if not root: return [] 
        queue = [root]
        res = []
        while queue:
            temp = [] // 用一维存放每一层的节点值
            for _ in range(len(queue)):  // 把位于同一层的节点存放在temp中;
                node = queue.pop(0) 
                temp.append(node.val)
                if node.left: queue.append(node.left)
                if node.right: queue.append(node.right)
            res.append(temp)

        return res
    

按之字形顺序打印二叉树

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

分析

解题思路:其实就是二叉树的层级遍历,不过是在遍历的时候,需要将偶数层的节点逆序。

关键点:每次只处理上次在queue中剩余的节点,这是上一层的所有节点。 处理完后刚好将下一层的所有节点(包含null)又全部放了进去。

数据结构: 用队列queue保存上一层的所有节点,一个list保存上一层的遍历结果。 (节点按照先进先出,处理到某个节点时,将某节点的左右子树入队)。

code

import java.util.LinkedList;
import java.util.ArrayList;
import java.util.Queue;

public class Solution {
    public ArrayList<ArrayList<Integer> > Print(TreeNode pRoot) {
        ArrayList<ArrayList<Integer>> res = new ArrayList<ArrayList<Integer> >();
        if(pRoot == null) return res;
        
        // LinkedList类实现了Queue接口,
        Queue<TreeNode> queue = new LinkedList<TreeNode>();
        int count = 0;
        //Queue使用时要尽量避免Collection的add()和remove()方法,add()和remove()方法在失败的时候会抛出异常。
        queue.offer(pRoot);
        // queue.isEmpty(), stack用empty();
        while(!queue.isEmpty()){
            ArrayList<Integer> list = new ArrayList<>();
            int size = queue.size();  // 得到队列的长度
            for(int i = 0; i < size; i++){
                TreeNode node = queue.poll(); // 对头出队;
                if(node == null){
                    continue;
                }
                if(count % 2 == 0){
                    list.add(node.val);
                }
                if(count % 2 == 1){
                    list.add(0, node.val); // 每次添加在第一个位置,自动实现该层的元素逆序;
                }
                
                queue.offer(node.left);
                queue.offer(node.right);
            }
            count++;
            //res.add(list); //如果为空,最后一个元素会变成[],例如: [[8],[10,6],[5,7,9,11],[]]
            if(queue.size() > 0){
                res.add(list);
            }
        }
        return res;
    }

}

写法二

import java.util.ArrayList;
import java.util.Queue;
import java.util.LinkedList;

public class Solution {
    public ArrayList<ArrayList<Integer> > Print(TreeNode pRoot) {
        ArrayList<ArrayList<Integer> > res = new ArrayList<ArrayList<Integer> >();
        if(pRoot == null) return res;
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(pRoot);
        int count = 0;
        while(! queue.isEmpty()){
            ArrayList<Integer> ans = new ArrayList<>();
            int size = queue.size();
            for(int i = 0; i < size; i++){
                TreeNode node = queue.poll();
                if(node == null) continue;
                if(count % 2 == 0){
                    ans.add(node.val);
                }
                if(count % 2 == 1){
                    ans.add(0, node.val);
                }
                if(node.left != null) queue.offer(node.left);
                if(node.right != null) queue.offer(node.right);
            }
            count++;
            res.add(ans);
        }
        return res;
    }

}

参考Krahets

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值