LeetCode 题目 116:填充每个节点的下一个右侧节点指针

作者介绍:10年大厂数据\经营分析经验,现任字节跳动数据部门负责人。
会一些的技术:数据分析、算法、SQL、大数据相关、python,欢迎探讨交流
欢迎加入社区:码上找工作
作者专栏每日更新:
LeetCode解锁1000题: 打怪升级之旅
python数据分析可视化:企业实战案例
漫画版算法详解
python源码解读
程序员必备的数学知识与应用

题目描述

给定一个完美二叉树,其所有叶子节点都在同一层,每个父节点都有两个子节点。二叉树的定义如下:

class Node:def __init__(self, val=0, left=None, right=None, next=None):self.val = valself.left = leftself.right = rightself.next = next

填充它的每个 next 指针,让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点,则将 next 指针设置为 None

初始状态下,所有 next 指针都被设置为 None

方法一:层序遍历(BFS)

解题步骤:
  1. 使用队列进行层序遍历。
  2. 对于每一层的节点,通过队列的长度来确定节点的数量。
  3. 遍历当前层的节点,将每个节点的 next 指向队列中的下一个节点。
  4. 最后一个节点的 next 指向 None
Python 代码示例
from collections import dequedef connect(root):"""使用层序遍历来填充每个节点的下一个右侧节点指针。参数:root (Node): 完美二叉树的根节点。返回:Node: 修改后的树的根节点。"""# 如果根节点为空,则直接返回Noneif not root:return None# 初始化队列,并将根节点加入队列queue = deque([root])# 当队列不为空时,进行层序遍历while queue:# 获取当前层的节点数量size = len(queue)# 遍历当前层的每个节点for i in range(size):# 从队列中取出一个节点node = queue.popleft()# 如果不是当前层的最后一个节点,将当前节点的next指向队列中的下一个节点if i < size - 1:node.next = queue[0]# 如果当前节点有左子节点,将左子节点加入队列if node.left:queue.append(node.left)# 如果当前节点有右子节点,将右子节点加入队列if node.right:queue.append(node.right)# 返回根节点return root

方法一利用层序遍历(BFS)来填充每个节点的下一个右侧节点指针,下面通过 ASCII 图形来说明这个方法的工作过程。

考虑一个完美二叉树如下所示:

        1/ \2   3/ \ / \4  5 6  7
算法图解

我们使用队列来按层级遍历这棵树,并设置每个节点的 next 指针。以下是各个步骤的图解说明:

初始状态
  1. 初始化队列以包含根节点。
队列: [1]
第一层处理
  1. 取出节点 1,发现它有左右子节点 2 和 3,将这两个节点加入队列。
队列: [2, 3]
next指针连接: 1 -> None
  1. 设置节点 1 的 next 指向 None(因为它是第一层的唯一节点)。
第二层处理
  1. 取出节点 2,由于它不是队列中的最后一个节点,设置 next 指向队列中的下一个节点(节点 3)。同时将节点 2 的子节点 4 和 5 加入队列。
队列: [3, 4, 5]
next指针连接: 2 -> 3
  1. 取出节点 3,设置 next 指向 None(因为它是当前层的最后一个节点),将节点 3 的子节点 6 和 7 加入队列。
队列: [4, 5, 6, 7]
next指针连接: 3 -> None
第三层处理
  1. 处理节点 4, 5, 6, 7 类似,按顺序设置 next 指针:
队列: [5, 6, 7]
next指针连接: 4 -> 5
队列: [6, 7]
next指针连接: 5 -> 6
队列: [7]
next指针连接: 6 -> 7
队列: []
next指针连接: 7 -> None

在每一步中,我们从队列中移除一个节点,如果该节点不是当前层的最后一个节点,则将其 next 指针设置指向队列中的下一个节点。这样,每一层的节点都通过 next 指针连成一条链。当处理完当前层的所有节点后,队列中就包含了下一层的所有节点,重复以上步骤直到队列为空。这样的遍历确保了每个节点的 next 指针正确地指向了其右侧的节点。

方法二:使用已建立的 next 指针

解题步骤:
  1. 从根节点开始,利用上一层的 next 指针来遍历和链接当前层的节点。
  2. 对于每个节点,链接其左子节点到右子节点,右子节点到下一个节点的左子节点(如果存在)。
Python 代码示例
def connect(root):"""利用已建立的 next 指针来填充每个节点的下一个右侧节点指针。参数:root (Node): 完美二叉树的根节点。返回:Node: 修改后的树的根节点。"""# 如果根节点为空,则直接返回Noneif not root:return None# 初始化leftmost指针,这个指针始终指向每一层的最左侧节点leftmost = root# 当左侧节点存在时,继续处理下一层while leftmost.left:# 使用head指针遍历当前层的节点,head初始指向当前层的最左侧节点head = leftmostwhile head:# 将当前节点的左子节点的next指向右子节点head.left.next = head.right# 如果当前节点的next不为空,将右子节点的next指向当前节点next的左子节点if head.next:head.right.next = head.next.left# 移动到当前层的下一个节点head = head.next# 移动到下一层的最左侧节点leftmost = leftmost.left# 返回根节点return root

方法三:递归法

解题步骤:
  1. 递归地连接每个节点的左子节点到其右子节点。
  2. 连接相邻子树的右子节点到左子节点。
Python 代码示例
def connect(root):if not root or not root.left:return rootroot.left.next = root.rightif root.next:root.right.next = root.next.leftconnect(root.left)connect(root.right)return root

方法四:使用额外的节点追踪下一层的开始

解题步骤:
  1. 使用一个额外的节点 dummy 来追踪每一层的开始。
  2. 通过一个循环连接同一层的所有节点。
Python 代码示例
def connect(root):if not root:return Nonecurrent = rootwhile current:dummy = Node(0)tail = dummywhile current:if current.left:tail.next = current.lefttail = tail.nextif current.right:tail.next = current.righttail = tail.nextcurrent = current.nextcurrent = dummy.nextreturn root

方法五:迭代优化

解题步骤:
  1. 类似于方法二,但使用迭代而非递归。
  2. 遍历每一层,连接相应的节点。
Python 代码示例
def connect(root):if not root:return Nonenode = rootwhile node and node.left:next_level = node.leftwhile node:node.left.next = node.rightnode.right.next =node.next.left if node.next else Nonenode = node.nextnode = next_levelreturn root

算法分析

  • 时间复杂度:所有方法都需要遍历每个节点,因此时间复杂度为 O(N),其中 N 是树中的节点数。
  • 空间复杂度
    • 方法一:O(N),需要额外的队列。
    • 方法二至五:O(1),只使用常数额外空间。

不同算法的优劣势对比

  • 层序遍历(方法一)直观且易于理解,但需要额外的空间来存储队列。
  • 使用已建立的 next 指针(方法二)是空间复杂度最优的解法,适合空间敏感的应用。
  • 递归法(方法三)代码简洁,但在非尾递归的编译器上可能导致栈溢出。
  • 使用额外节点(方法四)适合不熟悉指针操作的场景。
  • 迭代优化(方法五)提供了一个折中的解决方案,空间复杂度低,且较易于理解。

应用示例

这些方法可以用在需要层级遍历但希望节约空间的场景,如实时数据处理、游戏编程中的场景管理,或任何需要快速访问同一层级节点的数据结构设计中。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/10023.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C#上位机1ms级高精度定时任务

precisiontimer 安装扩展包 添加引用 完整代码 using PrecisionTiming;using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; us…

WinSCP软件出错:连接被意外关闭了

问题描述&#xff1a; WinSCP 登录 M3568 的 linux系统&#xff0c;提示 列出’/home/root’的目录项时出错&#xff0c;连接被意外关闭 具体提示如下图所示&#xff0c;列出’/home/root’的目录项时出错。 连接被意外关闭了 服务器发送命令的退出状态255 原因及解决&#xf…

notepad++安装 hex-editor插件

打开notepad 点击插件 搜索 hex-editor,点击右侧 安装install 安装成功后&#xff0c;在已安装插件中就有显示了

spring boot参数验证注解@NotNull、@NotBlank和@NotEmpty区别

目录 前言说明举例 前言 使用spring boot参数验证是常常会使用NotNull、NotBlank和NotEmpty三个判断是否不为空的注解&#xff0c;中文都有不能为空的意思&#xff0c;大部分使用者都傻傻分清它们之间到底有什么区别。今天就让咱们来一起探索它们之间的不同吧。 说明 注解名…

等保测评安全物理环境测评讲解

等保测评中的安全物理环境测评主要关注信息系统的物理安全保护措施&#xff0c;确保机房、设备和数据的物理安全。以下是安全物理环境测评的关键点讲解&#xff1a; 1. **物理位置选择**&#xff1a; - 机房应选择在具有防震、防风和防雨能力的建筑内。 - 应避免设在建筑…

【数据库】数据库指令

一。数据库打开 1.命令行 2.进入mysql mysql -uroot -p密码 3.退出 exit&#xff1b; 二。针对数据库的操作 1.创建数据库&#xff08;有分号&#xff09; create database student; 2.使用数据库 use student 3.删除数据库&#xff08;有分号&#xff09; drop database…

verilog基础语法之数据类型

verilog基础语法之数据类型 1、 wire类型2、 reg类型3、向量 Verilog最常用的数据类型有两种&#xff1a;线网&#xff08;wire&#xff09;和寄存器&#xff08;reg&#xff09;。其中&#xff0c;wire 类型表示硬件单元之间的物理连线&#xff0c;reg用来表示存储单元。 1、…

数据库调优-数据库优化

数据库优化 如何发现复杂的SQL有问题&#xff1f; 一个个去explain吗&#xff1f;你有没有这样的困惑&#xff0c;开发代码运行顺畅丝滑&#xff0c;上生产了却卡的一逼&#xff1f; 哈哈&#xff0c;相信大家都会遇到这样的问题&#xff01; sql 复制代码 # 举个栗子&…

4. 从感知机到神经网络

目录 1. 从感知机到神经网络 2. 最简单的神经网络 3. 激活函数的引入 1. 从感知机到神经网络 之前章节我们了解了感知机&#xff0c;感知机可以处理与门、非与门、或门、异或门等逻辑运算&#xff1b;不过在感知机中设定权重的工作是由人工来做的&#xff0c;而设定合适的&a…

【将Maven源改为国内阿里云镜像源】

目录 一、如何配置Maven镜像源&#xff1f; 二、Idea中的Maven配置 ​三、项目与你本地仓库和中央仓库的联系 一、如何配置Maven镜像源&#xff1f; 1、打开你的Maven用户设置文件(settings.xml)。默认情况下&#xff0c;该文件存在于你的用户目录下的.m2文件夹中。如果你没…

小程序内使用web-view组件嵌套H5页面,当H5页面更换了内容后,小程序里的h5页面不更新

这个问题是由于小程序缓存了H5的内容造成的&#xff0c;可以在H5链接后面拼接个参数&#xff0c;加上时间戳可做用于H5的版本号&#xff0c;这样每次访问都可以全新的链接展示内容避免缓存&#xff0c;代码如下wxml&#xff1a; <view> <web-view src"{{urlpath…

Kafka 执行命令超时异常: Timed out waiting for a node assignment

Kafka 执行命令超时异常&#xff1a; Timed out waiting for a node assignment 问题描述&#xff1a; 搭建了一个kafka集群环境&#xff0c;在使用命令行查看已有topic时&#xff0c;报错如下&#xff1a; [rootlocalhost bin]# kafka-topics.sh --list --bootstrap-server…

《机器学习by周志华》学习笔记-决策树-01

本书中的「决策树」有时指学习方法,有时指学得的树。 1、基本流程 1.1、概念 基本流程,亦称「判定树」 决策树(decision tree),是一种常见的机器学习方法。以二分类任务为例,我们希望从给定训练数据集学得一个模型,用以对新样例进行分离。 以二分类任务为例,可看作对…

一图看懂 | 蓝卓煤炭行业解决方案

煤炭是我国能源保障的“压舱石,也是国民经济中重要的支柱产业之一无论是发电、建材、造纸、冶金、化工等工业领域都离不开煤炭近年来&#xff0c;在“双碳”及能源安全双重背景下推动智能化技术与煤炭产业的融合发展提升煤矿安全生产能力的重要性与日俱增智慧矿山的建设已逐渐成…

CentOS 7安装配置docker

CentOS 7、8安装、配置docker 这里宿主机的型号选择是centos7.9.2009的版本 1.宿主机关闭防火墙和selinux&#xff0c;配置ipv4 #设置SELinuxdisabled vim /etc/selinux/config SELinuxdisabled 查看防火墙状态&#xff1a;firewall-cmd --state 关闭防火墙&#xff1a;syst…

selenium爬取TapTap评论

上一篇写的beautifulsoup和request爬取出的结果有误。首先&#xff0c;TapTap网页以JS格式解析&#xff0c;且评论并没有“下一页”&#xff0c;而是每次加载到底部就要进行等待重新加载。我们需要做的&#xff0c;是模仿浏览器的行为&#xff0c;所以这里我们用Selenium的方式…

2024年数维杯B题完整代码和思路论文讲解与分析

2024数维杯数学建模完整代码和成品论文已更新&#xff0c;获取↓↓↓↓↓ https://www.yuque.com/u42168770/qv6z0d/bgic2nbxs2h41pvt?singleDoc# 2024数维杯数学建模B题45页论文和代码已完成&#xff0c;代码为全部问题的代码 论文包括摘要、问题重述、问题分析、模型假设、…

【项目实战】使用Github pages、Hexo如何10分钟内快速生成个人博客网站

文章目录 一.准备工作1.安装git2.安装node安装 cnpm 3.使用 GitHub 创建仓库&#xff0c;并配置 GitHub Pages0.Github Pages是什么1. 在 GitHub 上创建一个新仓库2. 创建您的静态网站3. 启用 GitHub Pages4. 等待构建完成5. 访问您的网站 二. Hexo1.什么是Hexo2.安装Hexo1. 安…

【MySQL】求和查询,目标值int,但空数据时返回null的问题(Java)

问题分析 int selectDeviceMonthRepairCount(String deviceType, String month);<select id"selectDeviceMonthRepairCount" resultType"int">SELECT SUM(repair_count)FROM warranty_recordsWHERE device_type #{deviceType}AND nian_yue #{month…

【代码笔记】高并发场景下问题解决思路

高并发指的是在单位时间内&#xff0c;瞬时流量激增&#xff0c;系统需要同时处理大量并行的请求或操作。这种情况通常出现在面向大量用户或服务的分布式系统中&#xff0c;尤其是当用户请求高度集中时&#xff0c;比如促销活动、秒杀活动、注册抢课、热点事件、定时任务调度等…