二叉树 level order 遍历问题汇总

2023-10-28

一 如何确定层结束?

1 维护一个levelEnd,如果当前结点等于level end,更新levelEnd 为queue.back(),注意先判断queue是否empty,(最后一层结束后,queue就空了)。

2 维护一个curLevelNum 和 一个nextLevelNum,当curLevelNum count down 到0时候,更新curLevelNum 为 nextLevelNum,同时nextLevelNum清零

3 遍历完一层的时候,队列里存着的就是下一层的所有结点,int levelSize = queue.size(),就是下一层要取的个数

public ArrayList<ArrayList<Integer>> levelOrder(TreeNode root) {
    ArrayList result = new ArrayList();

    if (root == null)
        return result;

    Queue<TreeNode> queue = new LinkedList<TreeNode>();
    queue.offer(root);

    while (!queue.isEmpty()) {
        ArrayList<Integer> level = new ArrayList<Integer>(); // important
        int size = queue.size();
        for (int i = 0; i < size; i++) {
            TreeNode head = queue.poll();
            level.add(head.val);
            if (head.left != null)
                queue.offer(head.left);
            if (head.right != null)
                queue.offer(head.right);
        }
        result.add(level); // important
    }

    return result;
}

二 还有一种基于DFS + level号 的层次遍历方式

只是最终结果是按层次保存在vector<vector<int>>的,过程是dfs的。vector<vector<int>>第一维就是层,下标就是层号,第二维是每层的结点。dfs加一个维护递归深度的参数,访问到结点append到对应的层vector。

vector<vector<int> > levelOrder(TreeNode *root) {
        vector<vector<int>> res;
        dfs(root, 0, res);
        return res;
    }
    void dfs(TreeNode* root, int level, vector<vector<int>> &res) {
        if (!root) return;
        if (level == res.size()) res.push_back(vector<int>());
        res[level].push_back(root -> val);
        dfs(root -> left, level + 1, res);
        dfs(root -> right, level + 1, res);
    }


三 序列化二叉树

标准层次遍历的框架, “访问结点”的逻辑是,如果为空,append ”#“ '到结果集, 如果不为空,append 结点值到结果集,把左右子树入队(不管是不是NULL)。

最后要把trailing 的 ”#“ 去掉。或者维护队列里非空结点的个数,while (!q.empty() && numOfNotNull > 0),这样就不会添加不必要的“#”了

vector<string> serializeTree(TreeNode* root) {
	vector<string> res;
	if (root == NULL) return res;
	queue<TreeNode*> q;
	for (q.push(root); !q.empty(); ) {
		auto root = q.front(); q.pop();
		res.push_back(root ? to_string(root->val) : "#");
		if (root) {
			q.push(root->left);
			q.push(root->right);
		}
	}
	while(res.back() =="#") res.pop_back();
	return res;
}


三 反序列化二叉树

1)单独读取序列第一个,作为root,同时root 入队。

2)输入序列还有值:出队一个结点parent,(将为这个结点添加左、右孩子),从序列中读一个值,如果不是'#',创建一个新结点作为parent的左孩子,并加进队列,再读一个值(如果有的话),如果不是’#‘,创建一个新结点作为parent的右孩子,加进队列。是''#"的情况对应孩子域应为NULL,因为是默认值,所以不必处理。

def deserialize(self, data):
        # write your code here
        if len(data) == 0: return None
        root = TreeNode(data.pop(0))
        q , i = [], 0
        q.append(root)
        while i < len(data):
            node = q.pop(0)
            val, i = data[i], i + 1
            if val != '#': 
                node.left = TreeNode(int(val))
                q.append(node.left)
            if i < len(data):
                val, i = data[i], i + 1
                if val != '#':
                    node.right = TreeNode(int(val))
                    q.append(node.right)
        return root

TreeNode* deserializeLevelOrder(vector<string> &A) {
	if (A.empty()) return nullptr;
	queue<TreeNode*> q;
	auto root = new TreeNode(stoi(A[0]));
	q.push(root);
	for (int i = 1; i < A.size(); ++i) {
		auto node = q.front(); q.pop();
		if (A[i] != "#") {
			node->left = new TreeNode(stoi(A[i]));
			q.push(node->left);
		}
		if (++i < A.size() && A[i] != "#") {
			node->right = new TreeNode(stoi(A[i]));
			q.push(node->right);
		}
	}
	return root;
}


四 添加sibling 指针 

 1 dfs + levelTail 向量

dfs 加一个 维护递归深度的参数level,用一个level indexed vector  levelTail  保存每一层的尾。如果level == sevelTail.size() 则说明第一次到达该层,当前结点是level层的第一个结点,push_back 该结点。否则,levelTail[level] 指向当前结点,当前结点为新的level tail

void connect(TreeLinkNode *root, vector<TreeLinkNode*> &levelTail, int level){
	if (!root) return;
	if (level==levelTail.size()) levelTail.push_back(root);
	else{
		levelTail[level]->next = root;
		levelTail[level] = root;
	}
	connect(root->left, levelTail, level + 1);
	connect(root->right, levelTail, level + 1);
}



 2 层次遍历,利用已经添加好sibling指针的上一层作为队列

循环不变式是,当前层已经是一个表头为head的链表,下一层链表头为dummy,遍历当前链表,把下一层结点依次添加到下一层链表尾部,遍历结束后当前层链表头head更新为下一层的头 dummy.next

void connect(TreeLinkNode *root) {
        auto head = root;
        while (head ) {
            TreeLinkNode dummy(-1);
            for (TreeLinkNode *p = head, *prev = &dummy; p; p = p->next) {
                if (p->left) {
                    prev->next = p->left;
                    prev = prev->next;
                }
                if (p->right) {
                    prev->next = p->right;
                    prev = prev->next;
                }
            }
            head = dummy.next;
        }
    }





本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

二叉树 level order 遍历问题汇总 的相关文章

  • 学习笔记-二叉排序树

    二叉排序树 对于二叉排序树的任何一个非叶子节点 要求左子节点的值比当前节点的值小 右子节点的值比当前节点的值大 如果有相同的值 可以将该节点放在左子节点或右子节点 二叉排序树的创建和遍历 思路 比较节点的值 小于就放在左子节点 大于就放在右
  • 5.12 树和森林的遍历

    一 树的遍历 1 先根遍历 根左右 深度优先遍历 若树非空 先访问根节点 再依次对每棵子树进行先根遍历 树的先根遍历 void PreOrder TreeNode R if R NULL visit R 访问根结点 while R还有下一棵
  • Leetcode题解——26.树的子结构

    题目地址 剑指 Offer 26 树的子结构 力扣 LeetCode 目录 一 解题思路 一 大体思路 二 Search函数 三 Judge函数 二 代码实现 三 拓展思考 一 解题思路 一 大体思路 对于二叉树类的题目 一般会使用递归或层
  • 二叉树的基本概念及性质

    文章目录 一 基本概念 二 二叉树的种类 二叉树 满二叉树 完全二叉树 二叉搜索树 平衡二叉搜索树 三 二叉树的性质 性质一 性质二 性质三 性质四 性质五 一 基本概念 树是 n 个结点的有限集 在任意一颗非空树中 1 有且仅有一个特定的
  • 计算二叉树的第k层中所有叶子结点个数

    计算二叉树的第k层中所有叶子结点个数 Time Limit 1000MS Memory Limit 65535K 题型 编程题 语言 无限制 描述 二叉链表表示的二叉树 按先序次序输入二叉树中结点的值 字符表示空树 构造二叉链表表示的二叉树
  • 有趣的数据结构算法16——线索二叉树的构建

    有趣的数据结构算法16 线索二叉树的构建 什么是线索二叉树 线索二叉树的实现形式 线索二叉树的代码实现 线索二叉树的初始化 线索的串联 全部实现代码 GITHUB下载连接 深度遍历不仅仅有递归的方法噢 还有通过建立线索二叉树进行遍历的方法
  • 二叉树的结点数

    二叉树的结点数 10分 已知二叉树的结点结构定义如下 typedef struct NODE char data struct NODE lch rch NODE 说明 data 为数据域 均为英文大写字母 lch 和 rch 分别为指示左
  • java实现赫夫曼树以及赫夫曼编码和解码(用byte[])

    首先对于赫夫曼编码有个大概的理解 赫夫曼编码 Huffman Coding 又称霍夫曼编码 是一种编码方式 可变字长编码 VLC 的一种 Huffman于1952年提出一种编码方法 该方法完全依据字符出现概率来构造异字头的平均长度最短的码字
  • 【java实现二叉树的各种遍历方式】

    二叉树的各种遍历方式 通过递归方式 可实现二叉树的层级遍历 先序 中序 后序等遍历方式 package com ykq import java util ArrayList import java util List author ykq
  • 学习笔记-创建赫夫曼树

    赫夫曼树 给定 n 个权值作为 n 个叶子结点 构造一棵二叉树 若该树的带权路径长度 wpl 达到最小 称这样的二叉树为最优二叉树 也称为哈夫曼树 Huffman Tree 还有的书翻译为霍夫曼树 赫夫曼树是带权路径长度最短的树 权值较大的
  • java判断是否为序列二叉树 - Kaiqisan

    大家好 都吃晚饭了吗 我是Kaiqisan 是一个已经走出社恐的一般生徒 今天还是二叉树诶嘿嘿 首先还是明确一个概念 何为序列二叉树 答 中序遍历之后序列递增的二叉树为序列二叉树 比如这棵树 4 2 7 1 3 5 8 6 它的中序遍历结果
  • 力扣 - 102、二叉树的层序遍历(剑指Offer - 面试题32:从上到下打印二叉树)

    题目 给你一个二叉树 请你返回其按 层序遍历 得到的节点值 即逐层地 从左到右访问所有节点 示例 二叉树 3 9 20 null null 15 7 3 9 20 15 7 输出层序遍历的结果 3 9 20 15 7 分析 迭代法 用一个队
  • 面试经典(16)--二叉树根节点到指定节点的路径

    题目描述 给定一棵二叉树和二叉树中一个节点 输出根节点到指定节点间的路径 10 5 12 4 7 指定节点7 那么输出路径应该是10 5 7 分析与解法 这个题目是在我做过蛮多二叉树的题目之后总结的一道题目 发现很多题目都可以抽象出来这个题
  • 【数据结构】&&【C++】平衡搜索二叉树的模拟实现(AVL树)

    数据结构 C 平衡搜索二叉树的模拟实现 AVL树 一 AVL树的性质 二 AVL树的模拟实现 AVL树结点的定义 AVL树的插入 平衡因子的更新 左单旋 右单旋 双旋 左右旋 右左旋 AVL树的删除 检查是否是AVL树 三 完整代码 一 A
  • [课程复习] 数据结构之线性表、树、图、查找、排序经典算法复习

    作者最近在复习考博 乘此机会分享一些计算机科学与技术 软件工程等相关专业课程考题 一方面分享给考研 考博 找工作的博友 另一方面也是自己今后完成这些课程的复习资料 同时也是在线笔记 基础知识 希望对您有所帮助 不喜勿喷 无知 乐观 低调 谦
  • 【数据结构初阶】第七节.树和二叉树的基本操作

    作者简介 大家好 我是未央 博客首页 未央 303 系列专栏 Java初阶数据结构 每日一句 人的一生 可以有所作为的时机只有一次 那就是现在 文章目录 前言 一 二叉树的快速构建 二 二叉树的遍历 2 1 前序遍历 2 2 中序遍历 2
  • 数据结构--二叉树的二叉链表实现

    1 二叉树的二叉链表示意图 二叉链表的每个结点由三个域组成 数据域 左指针域和右指针域 左右指针分别用来保存左右孩子结点的存储地址 2 二叉链表实现二叉树 2 1 头文件及其定义 BTNode h pragma once typedef c
  • 二叉树的递归遍历、非递归遍历、层次遍历

    1 递归遍历 2 非递归遍历 3 层次遍历 1 递归遍历 在使用递归遍历的时候 每个节点会经过三次 public class PreInPosTraversal public static class Node public int val
  • JAVA实现二叉树的前、中、后序遍历(递归与非递归)

    最近在面试中遇到过问到二叉树后序遍历非递归实现的方法 之前以为会递归的解决就OK 看来还是太心存侥幸 在下一次面试之前 特地整理一下这个问题 首先二叉树的结构定义 java代码如下 public class Node private int
  • 数组双指针法汇总

    指针移动方向 相向夹逼 同向移动 维护的是一个区间还是只是关心指针指向的两个元素 同向移动的 维护一个区间的双指针法即滑动窗口法 2Sum 排序后两头往中间夹逼的双指针法 指针为什么可以不回退 即为什么可以i只 j只 当A i A j

随机推荐

  • spring cloud config 中的application.yml 和 bootstrap.yml

    bootstrap yml 在 application yml 之前加载 bootstrap yml可以理解成系统级别的一些参数配置 这些参数一般是不会变动的 一般使用bootstrap yml是由于有远程配置需要load到本地 一般它会包
  • 基于cubemx的stm32f103指纹模块(AS608)

    寒假这段时间自己做了个指纹锁玩 在这里写一下指纹模块的用法 一 测试 新到手的AS608模块 可以在软件中测试一下功能是否正常 在使用这个配套软件的时候 注意要搭配TTL转串口使用 连接电源线和串口线四根就可以了 注意在测试的时候 要找对C
  • OSPF矢量图及不规则区域设计理论

    任何一台路由器勾画出一个区域的连接 都是通过矢量图的方式来表示 在根据树型结构算法 来计算去往非直连网络的路径信息 路由在勾画连接只包含三个参数 两类节点和节点之间的链路 节点 路由器节点 stub节点 pc所在的网络 环回口连接的网络 网
  • 规则引擎调研报告

    背景 我们公司由于业务的极具扩大 每天经过系统的金额也达到了20亿美金左右 这个时候对资金的管控就不能像以前那样分散在不同的系统 由不同的部门负责了 所以说 我们成立了风控部门 必须成立了专门的研发团队负责风控需求 要开始做风控了 我受命去
  • JS 防抖与节流

    防抖与节流 1 防抖 debounce 1 1 定义 在连续的多次触发同一事件的情况下 给定一个固定的时间间隔 假设 300 ms 该时间间隔内若存在新的触发 则清除之前的定时器并重新计时 重新计时 300 ms 表现为在短时间多次触发同一
  • OnNotify与OnChildNotify以及CStatic的DrawItem实现源代码

    OnNotify是用于子控件向父窗口发送消息用的 该消息的接收对象是父窗口 OnChildNotify是子控件向父窗口发送消息后 父窗口反射消息给子窗口用的 该消息的接收对象是子窗口 如 CDialog上有一个CStatic 在CStati
  • Could not determine which ”make“ command to run. Check the ”make“ step in the build configuration.报错

    一般情况下 工具 gt 选项 gt 构建和运行 gt 构建套件 Kit 在编译器里选择一个合适的编译器即可 but 可能由于我下载了很多次qt 文件夹位置被我搞坏了 可以检查一下项目里的构建设置 构建目录里是否在红色部分构建目录下有所示文件
  • linux查询java进程的指令,查询内存的指令,查看JVM参数

    参看所有java进程占内存 CPU使用情况 top b n 1 grep java awk print PID 1 mem 6 CPU percent 9 mem percent 10 查看java中的进程 这个指令可以查到PID和包名字
  • 系统故障-asp.net环境有误

    外播要用电子分call系统 所以他们要安装电子分call系统 去了一看 他们的系统有些问题问题现象 1 所有的toolbar控件 所有的客户端都无法显示这个控件 但只有两个客户端可以显示 经分析是asp组件有问题 所以重新安装asp net
  • 在Vue中使用QRCode生成二维码

    首先安装依赖包 npm cnpm install save qrcode 下面是qrcode vue文件 在script标签导入qrcode import QRCode from qrcode 我一般是写在mounted里面 如果需要什么条
  • 解决springboot使用logback日志出现LOG_PATH_IS_UNDEFINED文件夹的问题

    application properties 加入以下配置 logback home logging path D logs esb producer logback xml
  • SQL server 数据类型转换

    在 SQL Server 中 CONVERT 和 PARSE 函数可以用于将一个数据值从一种数据类型转换为另一种数据类型 它们与 CAST 函数一样是 SQL Server 中常见的数据类型转换函数 CONVERT 函数 CONVERT 函
  • Scala学习(三)---函数式编程

    文章目录 1 面向对象编程 2 函数式编程是什么 3 函数定义 4 函数参数的特殊用法 5 函数至简原则 6 匿名函数 6 1 匿名函数化简原则 7 高阶函数 7 1 函数可以作为值进行传递 7 2 函数可以作为参数进行传递 7 3 函数可
  • Received fatal alert:handshake_failure 异常解决方法

    目录 1 背景 2 报错信息 3 问题分析 4 解决方法 1 背景 PCI认证 要求安全传输层协议由之前的TLS v1 0 TLS v1 1升级到TLS v1 2 2 报错信息 java lang Exception 接口调用失败 at c
  • 配置Tomcat成为系统服务

    配置Tomcat成为系统服务 这里已tomcat6为例 下载Zip版Tomcat 选择 32 bit Windows zip pgp md5 下载解压文件到指定目录 如 D ProgramFiles Tomcat6 进入D ProgramF
  • Python 微信公众号文章爬取

    Python 微信公众号文章爬取 一 思路 二 接口分析 三 实现 第一步 第二步 1 请求获取对应公众号接口 取到我们需要的fakeid 2 请求获取微信公众号文章接口 取到我们需要的文章数据 四 总结 一 思路 我们通过网页版的微信公众
  • Docker搭建私有仓库

    Docker搭建私有仓库 一 私有仓库搭建 1 拉取私有仓库镜像 docker pull registry 2 启动私有仓库容器 docker run name registry p 5000 5000 registry 3 打开浏览器输入
  • Python判断一个整数是否是回文数的三种方法

    方法一 逐位判断 原理 用一个while循环 将一个数每次都取出首位和末位 判断是否相等 只要有一次不相等退出即可 回文数的判断条件 加入一个变量位数 如果这个数是奇数 位数为1时 即最中间那一位数 此时退出即可 同理 偶数 位数为0时 退
  • LIN诊断实现MCU本地OTA升级

    一 目标 通过PC端上位机实现MCU本地的OTA升级 本篇文章对实现的目的 需要用到的第三方工具 LIN诊断帧 升级协议 MCU端升级过程以及PC端升级过程做详细说明 二 目的 最近在做MCU项目时需要将样机寄给客户进行验证 在客户的验证过
  • 二叉树 level order 遍历问题汇总

    一 如何确定层结束 1 维护一个levelEnd 如果当前结点等于level end 更新levelEnd 为queue back 注意先判断queue是否empty 最后一层结束后 queue就空了 2 维护一个curLevelNum 和