LeetCode116. 填充每个节点的下一个右侧节点指针

news2024/11/22 9:09:59

116. 填充每个节点的下一个右侧节点指针

文章目录

      • [116. 填充每个节点的下一个右侧节点指针](https://leetcode.cn/problems/populating-next-right-pointers-in-each-node/)
        • 一、题目
        • 二、题解
          • 方法一:迭代
          • 方法二:递归


一、题目

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

struct Node {
  int val;
  Node *left;
  Node *right;
  Node *next;
}

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

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

示例 1:

在这里插入图片描述

输入:root = [1,2,3,4,5,6,7]
输出:[1,#,2,3,#,4,5,6,7,#]
解释:给定二叉树如图 A 所示,你的函数应该填充它的每个 next 指针,以指向其下一个右侧节点,如图 B 所示。序列化的输出按层序遍历排列,同一层节点由 next 指针连接,'#' 标志着每一层的结束。

示例 2:

输入:root = []
输出:[]

提示:

  • 树中节点的数量在 [0, 212 - 1] 范围内
  • -1000 <= node.val <= 1000

进阶:

  • 你只能使用常量级额外空间。
  • 使用递归解题也符合要求,本题中递归程序占用的栈空间不算做额外的空间复杂度。

二、题解

方法一:迭代

算法思路:
本题需要将一棵完美二叉树的所有节点用next指针连接起来。解题思路是利用bfs层序遍历的方法。

具体实现:

  1. 利用队列deq进行层序遍历
  2. 每一层遍历时:
    2.1 保存该层队列大小size
    2.2 定义prev指针指向上一节点
    2.3 遍历队列中所有节点,将prev->next 指向当前节点
    2.4 更新prev为当前节点
    2.5 将左右孩子加入队列
  3. 返回根节点

通过在普通bfs过程中新增prev指针,记录上一节点,就可以正确连接同一层的节点。

/*
// Definition for a Node.
class Node {
public:
    int val;
    Node* left;
    Node* right;
    Node* next;

    Node() : val(0), left(NULL), right(NULL), next(NULL) {}

    Node(int _val) : val(_val), left(NULL), right(NULL), next(NULL) {}

    Node(int _val, Node* _left, Node* _right, Node* _next)
        : val(_val), left(_left), right(_right), next(_next) {}
};
*/

class Solution {
public:
    Node* connect(Node* root) {
        deque<Node*> deq;
        if(root == nullptr) return root;
        deq.push_back(root);
        while(!deq.empty()){
            int size = deq.size();
            Node *prev = nullptr;
            for(int i = 0; i < size; i++){
                Node *cur = deq.front();
                deq.pop_front();
                //用指针连接节点
                if(prev != nullptr) prev->next = cur;
                prev = cur;
                //加入左右孩子
                if(cur->left) deq.push_back(cur->left);
                if(cur->right) deq.push_back(cur->right);
            }
        }
        return root;
    }
};

算法分析:
时间复杂度 O(N): 遍历全部节点
空间复杂度 O(N): 队列最多存储全部节点

方法二:递归

题目要求我们填充每个节点的next指针,使其指向右侧节点。这道题是一个二叉树问题,我们可以采用递归的方式来解决。

算法思路:

  1. 首先,我们可以观察给定的二叉树。由于是一个完美二叉树,每个父节点都有两个子节点,并且所有叶子节点都在同一层。这意味着我们可以通过父节点来连接子节点的next指针。具体来说,每个节点的左子节点的next应该指向右子节点,而每个节点的右子节点的next应该指向其父节点的next节点的左子节点(如果感觉抽象可以仔细看看题干里给出的图)。
  2. 我们可以采用递归的方式进行连接。在递归的过程中,我们要确保每个节点的左子节点的next指向右子节点,并且每个节点的右子节点的next指向其父节点的next节点的左子节点。这样,我们可以在遍历整棵树的过程中正确地设置next指针。

具体实现:

  1. 我们可以定义一个递归函数connect,其输入参数为当前节点root
  2. 在函数内部,我们首先进行判断,如果root为空节点,直接返回root
  3. 如果root不为空,我们要进行连接操作。首先判断root的左子节点是否存在,若存在,则将root的左子节点的next指向root的右子节点。
  4. 接着,我们要判断root的右子节点是否存在,若存在,则将root的右子节点的next指向rootnext节点的左子节点(即右侧节点)。
  5. 接下来,我们继续递归地调用connect函数,分别传入root的左子节点和右子节点,以处理这两个子树的连接问题。
  6. 最后,函数返回root节点,递归过程结束。
/*
// Definition for a Node.
class Node {
public:
    int val;
    Node* left;
    Node* right;
    Node* next;

    Node() : val(0), left(NULL), right(NULL), next(NULL) {}

    Node(int _val) : val(_val), left(NULL), right(NULL), next(NULL) {}

    Node(int _val, Node* _left, Node* _right, Node* _next)
        : val(_val), left(_left), right(_right), next(_next) {}
};
*/

class Solution {
public:
    Node* connect(Node* root) {
        if (root == nullptr) return root;
        
        if (root->left) {
            root->left->next = root->right;
            if (root->next) {
                root->right->next = root->next->left;
            }
        }
        
        connect(root->left);
        connect(root->right);
        
        return root;
    }
};

算法分析:

  • 时间复杂度:假设树中节点的数量为N,由于我们需要遍历每个节点且每个节点的操作都是常数时间的,因此时间复杂度为O(N)。
  • 空间复杂度:由于我们使用了递归来进行遍历,递归调用会占用一定的栈空间。在最坏情况下,二叉树的高度为log(N),因此空间复杂度为O(logN)。由于题目要求不算递归程序的栈空间作为额外空间复杂度,所以这个解法是符合要求的。

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

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

相关文章

redis的并发安全问题:redis的事务VSLua脚本

redis为什么会发生并发安全问题&#xff1f; 在redis中&#xff0c;处理的数据都在内存中&#xff0c;数据操作效率极高&#xff0c;单线程的情况下&#xff0c;qps轻松破10w。反而在使用多线程时&#xff0c;为了保证线程安全&#xff0c;采用了一些同步机制&#xff0c;以及多…

grid map学习笔记1之Ubuntu18.04+ROS-melodic编译安装grid_map栅格地图及示例运行

文章目录 0 引言1 安装依赖和编译1.1 安装依赖1.2 下载编译 2 运行示例2.1 simple_demo2.2 tutorial_demo2.3 iterators_demo2.4 image_to_gridmap_demo2.5 grid_map_to_image_demo2.6 opencv_demo2.7 resolution_change_demo2.8 filters_demo2.9 interpolation_demo 0 引言 苏…

java项目之个人交友网站(ssm+mysql+jsp)

风定落花生&#xff0c;歌声逐流水&#xff0c;大家好我是风歌&#xff0c;混迹在java圈的辛苦码农。今天要和大家聊的是一款基于ssm的个人交友网站。技术交流和部署相关看文章末尾&#xff01; 开发环境&#xff1a; 后端&#xff1a; 开发语言&#xff1a;Java 框架&…

计算机启动过程uefi+gpt方式

启动过程&#xff1a; 一、通电 按下开关&#xff0c;不用多说 二、uefi阶段 通电后&#xff0c;cpu第一条指令是执行uefi固件代码。 uefi固件代码固化在主板上的rom中。 &#xff08;一&#xff09;uefi介绍 UEFI&#xff0c;全称Unified Extensible Firmware Interface&am…

基于C#的无边框窗体动画效果的完美解决方案 - 开源研究系列文章

最近在整理和编写基于C#的WinForm应用程序&#xff0c;然后碰到一个其他读者也可能碰到的问题&#xff0c;就是C#的Borderless无边框窗体的动画效果问题。 在Visual Studio 2022里&#xff0c;C#的WinForm程序提供了Borderless无边框窗体的样式效果&#xff0c;但是它没提供在无…

scrollIntoView()定位元素显示导致页面上移解决方法?

文章目录 项目场景&#xff1a;问题描述原因分析&#xff1a;解决方案&#xff1a;1、使用fixed固定定位父级元素2、控制父元素的scrollTop 项目场景&#xff1a; 在项目中需要根据当前组件的componentId来定位到页面的顶部显示。 问题描述 本来想着使用最传统的方法&#xff0…

MYSQL 练习2

练习2 创建company数据库在数据库中根据以下图示创建表&#xff0c;表结构如下&#xff0c;并插入以下数据&#xff0c;完成下面的sql。 ​ 表结构如下&#xff1a; salgrade表 salrade表数据 完成以下SQL编写&#xff1a; 修改emp表中sal字段为salary查找年薪在20000到3000…

JavaScript布尔逻辑

布尔逻辑是一种逻辑学上的分支&#xff0c;涉及真和假的值。布尔逻辑中使用的运算符仅返回真或假结果&#xff0c;这些运算符包括取反、与、或等。布尔逻辑通常用于电子学、计算机科学和数学等领域&#xff0c;其中真和假的值对于决策和控制流程非常重要。在计算机编程中&#…

60个AIGC专业术语手册;5种大模型微调方法总结;大模型创业潮成败点评;AIGC通用大模型产品测评报告 | ShowMeAI日报

&#x1f440;日报&周刊合集 | &#x1f3a1;生产力工具与行业应用大全 | &#x1f9e1; 点赞关注评论拜托啦&#xff01; &#x1f916; ChatGLM 金融大模型挑战赛&#xff0c;冠军送12B模型授权30W算力 GLM大模型联合安硕信息、阿里云、魔搭社区、北京交通大学&#xff0…

【并发专题】线程池ThreadPoolExecutorl底层原理源码分析

目录 前置知识课程内容一、线程池1.基本介绍2.Executor接口3.线程池的重点属性ctl字段RUNNING字段SHUTDOWN字段 二、线程池的创建及参数解读三、核心源码解读 学习总结 前置知识 Q1&#xff1a;终止一个线程的方法有哪些&#xff1f; 答&#xff1a;通常有4个方法。其中前2个是…

机械制造三维虚拟仿真实训的优点

机械制造三维虚拟仿真实训系统是一种基于计算机技术的机械原理仿真软件&#xff0c;它可以模拟各种机械系统的运动和受力情况&#xff0c;帮助用户深入了解机械原理的工作原理和应用。该系统采用三维建模技术&#xff0c;将机械系统的各个部分进行数字化建模&#xff0c;并通过…

科研院所用泛微搭建信创办公平台,统一办公,业务融合,安全便捷

国家全面推动重要领域的信创改造工作&#xff0c;要求到2027年底&#xff0c;对综合办公、经营管理、生产运营等系统实现“应替尽替、能替则替”。 科研机构作为智力、知识密集型机构&#xff0c;承载着大量数据、信息资产&#xff0c;数字化程度高&#xff0c;业务系统多样&a…

阿里云部署 ChatGLM2-6B 与 langchain+ChatGLM

1.ChatGLM2-6B 部署 更新系统 apt-get update 安装git apt-get install git-lfs git init git lfs install 克隆 ChatGLM2-6B 源码 git clone https://github.com/THUDM/ChatGLM2-6B.git 克隆 chatglm2-6b 模型 #进入目录 cd ChatGLM2-6B #创建目录 mkdir model #进入目录 cd m…

MySql增删改查基础

目录 1.基本操作 1.1新增 1.2查询 1.2.1指定查询 1.2.2排序查询 1.2.3分页查询 1.3修改 1.4删除 2.进阶操作 2.1键值约束 2.1.1主键约束 2.1.2唯一键约束 2.1.3非空约束 2.1.4默认值 2.1.5自增属性 ​编辑 2.1.6外键约束 2.1.7check子句 3.表的设计 3.1ER关…

海上港口三维数据可视化展示提升应急救援效率

3D可视化技术可以将复杂数据转化为生动的图形和模型&#xff0c;使得数据的关联和趋势更加明确和易于理解。通过使用3D模型和图形&#xff0c;我们可以更直观地观察数据之间的关系&#xff0c;发现隐藏在数据背后的规律和模式。例如&#xff0c;在工业领域&#xff0c;利用3D可…

jdk,jre和jvm三者的关系和区别

目录 一、三者的关系 二、JDK的概念 三、JRE的概念 四、JVM的概念 五、三者区别 一、三者的关系 从图中可以清楚地看到&#xff0c;他们之间的关系是JDK包含JRE, JRE又包含JVM。 因此&#xff0c;JDK包含JRE和JVM。 JDK JRE Java 开发工具包 [Java,Javac,Javadoc,Javap…

Python实现九宫格数独小游戏

1 问题 有1-9个数字&#xff0c;将他们填入一个3*3的九宫格中&#xff0c;使得他们的每行&#xff0c;每列&#xff0c;以及对角线上的和相等&#xff0c;且要求每个格子的数字不可以重复。使用python列出所有可能的组合。示例如下: 2 方法 每行&#xff0c;列&#xff0c;对角…

#pragma region用法

简介 #pragma region 是VS(Visio Studio)所特有的预处理语法&#xff08;其他IDE或者Cmake会报错&#xff09;&#xff0c;其可以用来收缩或者展开一段代码。 #pragma region MyRegion// ...Code content #pragma endregion 其中&#xff0c;MyRegion 即给这代码块所定义的名…

【python中级】将字符串按照固定长度分割

【python中级】将字符串按照固定长度分割 1、背景2、代码1、背景 近期有将图片进行base64编码成字符串的工作,参考博客: 【python中级】 base64编码将图片数据转化为成字符串 https://jn10010537.blog.csdn.net/article/details/131894686 我将图片编码成字符串后,再写到p…

地震反演基础知识1

文章目录 地震反演基础知识11. 基础知识1.1 正演反演1.2 地震数据1.3 速度模型1.4 道1.5 FWI的端到端深度学习1.6 传统FWI vs. DL-FWI 2. 数据信息2.1 数据集的层级关系2.2 SEG盐体数据2.3 OpenFWI数据集 地震反演基础知识1 1. 基础知识 1.1 正演反演 正演 根据地下介质的参…