阿里淘天/京东 CodeTop LeetCode103.二叉树的锯齿形层序遍历

1.思路:要求二叉树的层序遍历的打印顺序交替变化。考虑层序遍历 + 双端队列。 利用双端队列的两端皆可添加元素的特性,设打印列表(双端队列)tmp,并规定:

(1)偶数层(第0层也是偶数层):从左到右正常顺序。

(2)奇数层:从右到左反转顺序。

2.过程:

(1)特例处理:当树的根节点为空时,直接返回空列表\[\]。

(2)初始化:打印结果空列表res,包含根节点的双端队列deque。

(3)BFS循环:当deque为空时跳出。

(a)新建列表tmp,用于临时存储当前层的打印结果。

(b)当前层循环打印:循环次数为当前层的节点数(即deque的长度)。

------出队:队首元素出队,记为node。

------打印:若为奇数层,将node.val添加至tmp尾部;否则,添加至tmp头部。

------添加子节点:若node的左(右)子节点不为空,则加入deque。

(c)将当前层的结果tmp转化为list并添加入res。

(4)返回值:返回打印结果列表res即可。

复杂度分析:

(1)时间复杂度:O(n),其中n为二叉树的节点数量,即BFS需要循环n次,占用O(n)。双端队列的队首和队尾的添加和删除操作的时间复杂度均为O(1)。

(2)空间复杂度:O(n),最差情况下,即当树为满二叉树时,最多有n/2个树节点同时在deque中,使用O(n)大小的额外空间。

附代码:

java 复制代码
class Solution {
    public List<List<Integer>> zigzagLevelOrder(TreeNode root) {
        if(root == null){
            return new ArrayList<>();
        }
        LinkedList<TreeNode> queue = new LinkedList<>();
        List<List<Integer>> res = new ArrayList<>();
        queue.add(root);
        while (queue.size() > 0) {
            int size = queue.size();
            List<Integer> tmp = new ArrayList<>();
            for(int i = 0;i < size;i++) {
                TreeNode t = queue.remove();
                if (res.size() % 2 == 0){
                    tmp.addLast(t.val);
                }else{
                    tmp.addFirst(t.val);
                } 
                if (t.left != null){
                    queue.add(t.left);
                }
                if(t.right != null){
                    queue.add(t.right);
                }
            }
            res.add(tmp);
        }
        return res;
    }
}

ACM模式:

java 复制代码
import java.util.Scanner;
import java.util.ArrayList;
import java.util.List;
import java.util.LinkedList;

// 定义二叉树节点类
class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;

    TreeNode(int val) {
        this.val = val;
        this.left = null;
        this.right = null;
    }
}

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        // 读取输入的一行,并去除首尾空格
        String input = scanner.nextLine().trim();

        // 构建二叉树
        TreeNode root = buildTree(input);

        // 获取锯齿形层序遍历结果
        Solution solution = new Solution();
        List<List<Integer>> result = solution.zigzagLevelOrder(root);

        // 输出结果:每层占一行,节点之间用空格分隔
        for (List<Integer> list : result) {
            for (int j = 0; j < list.size(); j++) {
                System.out.print(list.get(j));
                if (j < list.size() - 1) {
                    System.out.print(" ");
                }
            }
            System.out.println();
        }

        scanner.close();
    }

    // 根据输入字符串构建二叉树(层序遍历格式,null表示空节点)
    private static TreeNode buildTree(String input) {
        if (input == null || input.length() == 0) {
            return null;
        }

        String[] values = input.split(" ");
        if (values.length == 0 || values[0].equals("null")) {
            return null;
        }

        TreeNode root = new TreeNode(Integer.parseInt(values[0]));
        LinkedList<TreeNode> queue = new LinkedList<>();
        queue.add(root);
        int i = 1;

        while (!queue.isEmpty() && i < values.length) {
            TreeNode current = queue.remove();

            // 处理左子节点
            if (i < values.length && !values[i].equals("null")) {
                current.left = new TreeNode(Integer.parseInt(values[i]));
                queue.add(current.left);
            }
            i++;

            // 处理右子节点
            if (i < values.length && !values[i].equals("null")) {
                current.right = new TreeNode(Integer.parseInt(values[i]));
                queue.add(current.right);
            }
            i++;
        }

        return root;
    }
}

// 解题类,包含锯齿形层序遍历的方法
class Solution {
    public List<List<Integer>> zigzagLevelOrder(TreeNode root) {
        if(root == null){
            return new ArrayList<>();
        }
        LinkedList<TreeNode> queue = new LinkedList<>();
        List<List<Integer>> res = new ArrayList<>();
        queue.add(root);
        while (queue.size() > 0) {
            int size = queue.size();
            List<Integer> tmp = new ArrayList<>();
            for(int i = 0;i < size;i++) {
                TreeNode t = queue.remove();
                if (res.size() % 2 == 0){
                    tmp.addLast(t.val);
                }else{
                    tmp.addFirst(t.val);
                } 
                if (t.left != null){
                    queue.add(t.left);
                }
                if(t.right != null){
                    queue.add(t.right);
                }
            }
            res.add(tmp);
        }
        return res;
    }
}
相关推荐
Severus_black37 分钟前
【初阶数据结构与算法】八大排序之非比较排序(计数排序),一次性讲清!
数据结构·算法·排序算法
QiLinkOS1 小时前
从技术到资产的跃迁:企业专利布局的深层逻辑
c语言·数据结构·c++·单片机·嵌入式硬件·算法·开源
影寂ldy2 小时前
C#Dictionary字典
数据结构
Lucky_ldy5 小时前
数据结构从入门到精通:顺序表
数据结构·链表
熬夜敲代码的猫5 小时前
AVL树(C++详解版)
数据结构·c++·算法
并不喜欢吃鱼6 小时前
从零开始 C++-----十一【C++ 数据结构】红黑树全解析:从定义到工程实现(一文搞定,十分详细)
开发语言·数据结构·c++
星恒随风6 小时前
C语言数据结构排序算法详解(上):从插入排序、希尔排序到选择排序、堆排序
c语言·数据结构·笔记·学习·排序算法
迈巴赫车主6 小时前
蓝桥杯21247弹跳鞋java
java·开发语言·数据结构·算法·职场和发展·蓝桥杯
Cthy_hy6 小时前
Python算法竞赛:集合去重+字典映射 核心用法一站式整理
数据结构·python·算法
happymaker06267 小时前
LeetCodeHot100——盛水最多的容器
数据结构·算法·leetcode·双指针·hot100