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

作者介绍: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):if not root:return Nonequeue = deque([root])while queue:size = len(queue)for i in range(size):node = queue.popleft()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

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

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

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

方法二:使用已建立的 next 指针(优化版)

解题步骤:
  1. 从根节点开始,利用上一层的 next 指针来遍历和链接当前层的节点。
  2. 对于每个节点,链接其左子节点到右子节点,右子节点到下一个节点的左子节点(如果存在)。
Python 代码示例
def connect(root):if not root:return None# 从根节点开始current = 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 root# 连接左右子节点if root.left and root.right:root.left.next = root.right# 连接跨越父节点的子节点if root.right and root.next:root.right.next = root.next.left if root.next.left else root.next.right# 递归子节点connect(root.right)connect(root.left)return root

方法四:迭代法

解题步骤:
  1. 使用外部指针追踪下一层的起始点。
  2. 使用内部循环来连接同层的所有节点。
Python 代码示例
def connect(root):if not root:return Nonehead = rootwhile head:dummy = Node(0)tail = dummywhile head:if head.left:tail.next = head.lefttail = tail.nextif head.right:tail.next = head.righttail = tail.nexthead = head.nexthead = dummy.nextreturn root

方法五:迭代优化

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

算法分析

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

不同算法的优劣势对比

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

应用示例

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

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

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

相关文章

7-Zip介绍:一个强大的开源压缩工具

介绍 7-Zip 是一个开源的文件压缩和解压缩工具&#xff0c;具有高压缩比和快速解压的特点。它支持多种压缩格式&#xff0c;包括 7z、ZIP、RAR、GZIP、TAR 等&#xff0c;是一个功能丰富、易于使用的压缩工具。本文将介绍7-Zip的特点、优缺点以及其在实际应用中的作用。 特点…

3. 多层感知机算法和异或门的 Python 实现

前面介绍过感知机算法和一些简单的 Python 实践&#xff0c;这些都是单层实现&#xff0c;感知机还可以通过叠加层来构建多层感知机。 2. 感知机算法和简单 Python 实现-CSDN博客 1. 多层感知机介绍 单层感知机只能表示线性空间&#xff0c;多层感知机就可以表示非线性空间。…

Ubuntu20.04 设置路由器

1. 网络拓扑图 2. 查看网卡信息 ip a得出如下网卡信息&#xff0c;enp1s0和enp2s0为两个网卡名称&#xff0c;以及相关两个网卡的详细信息&#xff0c;不同设备的网卡名称可能不一样 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group defaul…

使用python获取一下microsoft的搜索积分

主要使用的库是pyautogui PyAutoGUI接管了鼠标、键盘使用权,基本上完全照搬人的操作; 主要步骤如下: 登录edge浏览器打开搜索页面 找到搜索框的位置坐标使用pyautogui模拟点击搜索框模拟输入搜索文字模拟点击键盘enter键重复以上动作伪代码如下: import pyautogui import ti…

图像处理中的方向梯度直方图纹理特征提取方法

方向梯度直方图&#xff08;Histogram of Oriented Gradients&#xff0c;HOG&#xff09;是一种常用的用于图像纹理特征提取的方法。HOG算法通过计算图像中各个局部区域的梯度方向和强度&#xff0c;然后构建一个直方图来描述图像的纹理特征。 以下是使用方向梯度直方图进行纹…

WM Transaction Code 仓库管理模块事务代码大全

1.1 LE-WM 仓库管理 Warehouse Management 仓库管理事务码 描述 LB01 Create Transfer Requirement 创建转储需求 LB02 Change transfer requirement 修改转储需求 LB03 Display Transfer Requirement 显示转储需求 LB10 TRs for Storage Type 按仓储类型的转储请求 …

推荐4个可用的github国内镜像

Github是全球最大的代码托管云平台&#xff0c;超过1亿用户在平台上分享代码及数据&#xff0c;深受生物信息学软件开发者的喜爱&#xff0c;并且现在发表文章&#xff0c;若涉及到代码&#xff0c;编辑还要求我们把代码及数据存放在github上&#xff0c;以便检查数据的真实性和…

商务通设置对话永远在迷你小窗口对话

系统设置--参数设置--PC对话窗口--迷你对话窗口-- 点击浮动图标或接受邀请时在当前页面弹出迷你对话窗口

frida hook java

代码例子 原函数&#xff1a; hook函数&#xff1a; if(Java.available){Java.perform(function(){var a Java.use("com.sankuai.waimai.foundation.utils.security.a");a.a.overload("java.lang.String","java.lang.String","long"…

Angular进阶:深入理解RxJS在Angular应用中的高效运用

RxJS&#xff08;Reactive Extensions for JavaScript&#xff09;是JavaScript的一个响应式编程库&#xff0c;特别适用于处理异步数据流。 在Angular应用中&#xff0c;RxJS的高效运用主要体现在&#xff1a; 异步操作处理 RxJS的核心优势在于处理异步操作&#xff0c;如H…

【论文合集1】- 存内计算加速机器学习

本章节论文合集&#xff0c;存内计算已经成为继冯.诺伊曼传统架构后&#xff0c;对机器学习推理加速的有效解决方案&#xff0c;四篇论文从存内计算用于机器学习&#xff0c;模拟存内计算&#xff0c;对CNN/Transformer架构加速角度阐述存内计算。 【1】WWW: What, When, Where…

maven 配置(远程仓库管理)

maven 配置 如何上传至远程仓库单一项目(需配置pom.xml与setting.xml)全局(显式激活) profile (可实现: 单一项目配置、单一用户配置、全局配置)如何使用profile 公司因为jar包管理混乱(本地缺这个缺那个的)&#xff0c;因此建了一个私库。但是仍然很混乱&#xff0c;因为maven…

Java自定义注解:从定义到解析,再到AOP切面与日志打印应用

目录 一、注解定义二、注解解析三、自定义注解结合AOP切面四、自定义注解用于日志打印五、区别总结六、应用场景总结 在Java开发中&#xff0c;注解是一种强大的元编程工具&#xff0c;它可以帮助我们提升代码的可读性和功能性。本文将深入探讨如何创建和使用自定义注解&#x…

Java JVM 浅析

为什么要有JVMJVM是什么&#xff1f;JVM的工作流程和组成部分JVM规范和JVM实现JVM原理详解 带着以上问题&#xff0c;我将尝试对JVM作出一些简单的介绍。 一、JVM 简介 在90年代初&#xff0c;软件开发面临一个大问题&#xff0c;即不同的操作系统和硬件架构要求开发不同的版本…

Acrobat Pro DC 2023 for Mac:PDF处理的终极解决方案

Acrobat Pro DC 2023 for Mac为Mac用户提供了PDF处理的终极解决方案。它具备强大的文档处理能力&#xff0c;无论是查看、编辑还是创建PDF文件&#xff0c;都能轻松胜任。在编辑功能方面&#xff0c;Acrobat Pro DC 2023支持对文本、图像进行精准的修改和调整&#xff0c;还能添…

从RAID 0到RAID 10:全面解析RAID技术与应用

&#x1f407;明明跟你说过&#xff1a;个人主页 &#x1f3c5;个人专栏&#xff1a;《Linux &#xff1a;从菜鸟到飞鸟的逆袭》&#x1f3c5; &#x1f516;行路有良友&#xff0c;便是天堂&#x1f516; 目录 一、前言 1、磁盘阵列简介 2、磁盘阵列诞生背景 3、硬件RA…

联邦学习框架VeryFL

一、介绍 VeryFL(Variable-Fidelity Learning)是一种联邦学习框架。联邦学习是一种分布式机器学习方法,其中许多参与者(例如移动设备或边缘设备)共同训练一个全局模型,而不需要将他们的数据上传到中央服务器。与传统的集中式方法相比,联邦学习具有更高的隐私性和安全性…

正点原子[第二期]Linux之ARM(MX6U)裸机篇学习笔记-14-主频和时钟配置

前言&#xff1a; 本文是根据哔哩哔哩网站上“正点原子[第二期]Linux之ARM&#xff08;MX6U&#xff09;裸机篇”视频的学习笔记&#xff0c;在这里会记录下正点原子 I.MX6ULL 开发板的配套视频教程所作的实验和学习笔记内容。本文大量引用了正点原子教学视频和链接中的内容。…

MPAndroidChart 详细使用 - BarChart

chart下面的方法 getDescription().setEnabled(boolean enabled);//设置描述是否显示 setPinchZoom(boolean enabled);//设置x轴和y轴能否同时缩放。默认是否 setScaleEnabled(boolean enabled);//是否支持缩放 setScaleXEnabled(boolean enabled);//启用/禁用x轴上的缩放 setS…

示波器基础1-带宽

数字示波器最重要的基本特征之一是其带宽&#xff0c;了解带宽及其对技术指标的影响对于选择合适的示波器非常有帮助。 这里我们对示波器带宽的一些基本方面做一简要介绍。 当我们谈到示波器的带宽时&#xff0c;重要的是要区分模拟带宽和数字带宽。模拟带宽主要受仪器模拟输入…