117. 填充每个节点的下一个右侧节点指针 II : 详细图解 O(1) 空间构建过程

news2024/11/28 12:55:31

题目描述

这是 LeetCode 上的 「117. 填充每个节点的下一个右侧节点指针 II」 ,难度为 「中等」

Tag : 「BFS」、「链表」

给定一个二叉树:

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

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

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

示例 1: alt

输入:root = [1,2,3,4,5,null,7]

输出:[1,#,2,3,#,4,5,7,#]

解释:给定二叉树如图 A 所示,你的函数应该填充它的每个 next 指针,以指向其下一个右侧节点,如图 B 所示。序列化输出按层序遍历顺序(由 next 指针连接),'#' 表示每层的末尾。

示例 2:

输入:root = []

输出:[]

提示:

  • 树中的节点数在范围

进阶:

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

BFS - 层序遍历

一个最直观的做法,是利用 BFS 对树进行「层序遍历」。

每个 BFS 回合中,对整层节点进行处理。

首先通过 pop 拿到当前节点,同时通过 peek 拿到当前层的下一节点,并建立 next 关系,注意需要跳过每层的最后一个节点。

Java 代码:

class Solution {
    public Node connect(Node root) {
        Node ans = root;
        if (root == nullreturn ans;
        Deque<Node> d = new ArrayDeque<>();
        d.addLast(root);
        while (!d.isEmpty()) {
            int sz = d.size();
            while (sz-- > 0) {
                Node a = d.pollFirst();
                if (sz != 0) a.next = d.peekFirst();
                if (a.left != null) d.addLast(a.left);
                if (a.right != null) d.addLast(a.right);
            }
        }
        return ans;
    }
}

C++ 代码:

class Solution {
public:
    Node* connect(Node* root) {
        Node* ans = root;
        if (root == nullptrreturn ans;
        deque<Node*> d;
        d.push_back(root);
        while (!d.empty()) {
            int sz = d.size();
            while (sz-- > 0) {
                Node* a = d.front();
                d.pop_front();
                if (sz != 0) a->next = d.front();
                if (a->left) d.push_back(a->left);
                if (a->right) d.push_back(a->right);
            }
        }
        return ans;
    }
};

Python 代码:

class Solution:
    def connect(self, root: 'Node') -> 'Node':
        ans = root
        if root is None:
            return ans
        d = [root]
        while d:
            sz = len(d)
            for i in range(sz):
                a = d.pop(0)
                if i != sz - 1:
                    a.next = d[0]
                if a.left:
                    d.append(a.left)
                if a.right:
                    d.append(a.right)
        return ans

TypeScript 代码:

function connect(root: Node | null): Node | null {
    let ans = root;
    if (root == nullreturn ans;
    const d = [root];
    while (d.length > 0) {
        let sz = d.length;
        while (sz-- > 0) {
            const a = d.shift() as Node;
            if (sz != 0) a.next = d[0];
            if (a.left) d.push(a.left);
            if (a.right) d.push(a.right);
        }
    }
    return ans;
};
  • 时间复杂度:
  • 空间复杂度:

BFS - 逐层构建

上述解法中,每一层节点的 next 关系的构建都是独立的。我们构建第 层的 next 关系时,并没有利用已建好的到第 层的 next 关系。

实际上,每一层构建好的 next 关系都可看做「链表」,可参与到下一层 next 关系的构建,同时由于所有节点的起始 next 指向都是 null,相当于首层的 next 关系已经默认建好了。

我们使用图解方式,来感受逐层构建过程:

image.png
image.png
image.png
image.png
image.png
image.png

Java 代码:

class Solution {
    public Node connect(Node root) {
        Node ans = root;
        if (root == nullreturn ans;
        Node cur = root;
        while (cur != null) {
            Node head = new Node(-1), tail = head;
            for (Node i = cur; i != null; i = i.next) {
                if (i.left != null) tail = tail.next = i.left;
                if (i.right != null) tail = tail.next = i.right;
            }
            cur = head.next;
        }
        return ans;
    }
}

C++ 代码:

class Solution {
public:
    Node* connect(Node* root) {
        auto ans = root;
        if (root == nullptrreturn ans;
        auto cur = root;
        while (cur) {
            auto head = new Node(-1), tail = head;
            for (auto i = cur; i != nullptr; i = i->next) {
                if (i->left) tail = tail->next = i->left;
                if (i->right) tail = tail->next = i->right;
            }
            cur = head->next;
        }
        return ans;
    }
};

Python 代码:

class Solution:
    def connect(self, root: 'Node') -> 'Node':
        ans = root
        if not root:
            return ans
        cur = root
        while cur:
            head = Node(-1)
            tail = head
            i = cur
            while i:
                if i.left:
                    tail.next = i.left
                    tail = tail.next
                if i.right:
                    tail.next = i.right
                    tail = tail.next
                i = i.next
            cur = head.next
        return ans

TypeScript 代码:

function connect(root: Node | null): Node | null {
    let ans = root;
    if (root == nullreturn ans;
    let cur = root;
    while (cur != null) {
        let head = new Node(-1), tail = head;
        for (let i = cur; i != null; i = i.next) {
            if (i.left) tail = tail.next = i.left;
            if (i.right) tail = tail.next = i.right;
        }
        cur = head.next;
    }
    return ans;
};
  • 时间复杂度:
  • 空间复杂度:

最后

这是我们「刷穿 LeetCode」系列文章的第 No.117 篇,系列开始于 2021/01/01,截止于起始日 LeetCode 上共有 1916 道题目,部分是有锁题,我们将先把所有不带锁的题目刷完。

在这个系列文章里面,除了讲解解题思路以外,还会尽可能给出最为简洁的代码。如果涉及通解还会相应的代码模板。

为了方便各位同学能够电脑上进行调试和提交代码,我建立了相关的仓库:https://github.com/SharingSource/LogicStack-LeetCode 。

在仓库地址里,你可以看到系列文章的题解链接、系列文章的相应代码、LeetCode 原题链接和其他优选题解。

更多更全更热门的「笔试/面试」相关资料可访问排版精美的 合集新基地 🎉🎉

本文由 mdnice 多平台发布

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

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

相关文章

【256MB+256MB】起,含税低至88元!飞凌嵌入式FET113i-S全国产核心板上市

超低价、超灵活、超全能&#xff01;飞凌嵌入式FET113i-S全国产核心板正式发布&#xff01;整板采用100%国产工业级元器件&#xff0c;含税价最低仅需88元&#xff01; FET113i-S核心板基于全志T113-i工业级处理器开发设计&#xff0c;主频1.2GHz&#xff0c;配备多核多架构&a…

2023 冬季波卡黑客松先导预告:三大赛题、30 万美金奖赏 Web3 探险者!

用「熊市」形容 2023 年的 web3 行业似乎并不准确。狂热之后的巨头暴雷、黑客攻击和投资锐减并未使 web3 发展停滞。比特币 ETF 进展引人瞩目&#xff0c;新的技术进展、新的 web3 物种也正在出现&#xff0c;而 AI 等技术的发展也在为 web3 应用带来新的想象力。2023 或许又是…

微信小程序-form表单-获取用户输入文本框的值

微信小程序-form表单-获取用户输入文本框的值 data: {userName: ,userPwd:""},//获取用户输入的用户名 userNameInput:function(e) {this.setData({userName: e.detail.value}) }, passWdInput:function(e) {this.setData({userPwd: e.detail.value}) }, //获取用户输…

Nacos本地修改编译源码2.2.3

下载Nacos源码 由于github访问速度慢&#xff0c;所以在gitee上下载 git clone https://gitee.com/mirrors/Nacos.git切换2.2.3版本 git checkout 2.2.3或者直接下载2.2.3的源码 本地编译 源码导入idea&#xff0c;然后编译 mvn -Dmaven.test.skiptrue -Drat.skiptrue c…

电力/税务单位宣传稿考核,投稿报纸怎么做

在当今信息传播的多元化时代&#xff0c;纸质媒体仍然是企业、机关事业单位宣传的重要平台。不管的本地报纸&#xff0c;还是省级报纸或国家级报纸、网媒&#xff0c;可能都有考核要求。 要在报纸上发表文稿&#xff0c;一般需要以下步骤&#xff1a; 1、选择合适的报纸&#x…

用斐波那契分解正整数

https://vjudge.net/contest/591700#problem/C 观察这个形式&#xff0c;如果交替做&#xff0c;就是个斐波那契数列 打表可得&#xff0c;任何正整数都可以大约由 log ⁡ \log log 个斐波那契数加起来 然后直接拼斐波那契数即可 #include<bits/stdc.h> using namesp…

REF615C-D HCFFAEAGABC2BAA1XD 一体化工业解决方案

REF615C-D HCFFAEAGABC2BAA1XD 一体化工业解决方案 Crimson Control使客户能够使用IEC 61131编程语言——如梯形逻辑、功能块、结构化文本和指令列表——通过开发类似可编程逻辑控制器(PLC)或远程遥测单元(RTU)的逻辑控制来解决特定的应用需求&#xff0c;而无需额外的费用。该…

TikTok小企业营销:崭露头角的新机遇

在数字时代&#xff0c;社交媒体已经成为推广和营销的强大工具。其中&#xff0c;TikTok以其独特的短视频内容和庞大的用户基础&#xff0c;为小企业提供了前所未有的营销机会。本文将深入探讨TikTok小企业的崛起&#xff0c;以及它所带来的新机会和挑战。 TikTok&#xff1a;数…

新建Git仓库后!如何将本地项目直接推送上到git仓库中的详细教程!

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、Git新建仓库二、来到你的本地仓库 前言 我们在git新建仓库后&#xff0c;如何直接在本地的项目文件夹中直接推送到git仓库中呢&#xff01;那么下面是详细…

QT6/5无痛安装和扩展,新手专用

QT6安装教程 注意在QT5.14.2以后版本只支持在线安装&#xff0c;所以如果需要离线exe版本&#xff0c;请安装5.14.2版本。这里是基于6.5版本Windows10的安装 如果觉得有用的话&#xff0c;请给个点赞收藏 1、安装链接 官方链接 qt官方链接&#xff1a;https://download.qt.io…

Angular异步数据流编程

1 目前常见的异步编程的几种方法 首先给出一个异步请求的实例&#xff1a; import {Injectable} from angular/core;Injectable({providedIn: root }) export class RequestServiceService {constructor() {}getData() {setTimeout(() > {let res zhaoshuai-lcreturn res…

uniapp写一个计算器用于记账(微信小程序,APP)

提要&#xff1a;自己用uniapp写了一个记账小程序&#xff08;目前是小程序&#xff09;&#xff0c;写到计算器部分&#xff0c;在网上找了别人写的计算器&#xff0c;大多数逻辑都是最简单的&#xff0c;都不能满足一个记账计算器的基本逻辑。与其在网上找来找去&#xff0c;…

Okta 数据泄露暴露了员工的个人信息

Okta 警告近 5000 名员工&#xff0c;他们的个人信息在第三方供应商遭到破坏后泄露。 Okta 是一家位于旧金山的云身份和访问管理解决方案提供商&#xff0c;其单点登录 (SSO)、多重身份验证 (MFA) 和 API 访问管理服务被全球数千个组织使用。 该 数据泄露通知 警告称&#xf…

PS学习笔记合集

2.一些快捷键 一、放大快捷键 Ctrl&#xff1a;在画布中点击一次&#xff0c;即可放大一次&#xff0c;可多次点击。 CtrlShift&#xff1a;在画布中点击一次&#xff0c;即可放大到适合窗口大小。 CtrlAlt&#xff1a;在画布中点击一次&#xff0c;即可放大到适合窗口大小&a…

Leetcode刷题详解——二叉树的所有路径

1. 题目链接&#xff1a;257. 二叉树的所有路径 2. 题目描述&#xff1a; 给你一个二叉树的根节点 root &#xff0c;按 任意顺序 &#xff0c;返回所有从根节点到叶子节点的路径。 叶子节点 是指没有子节点的节点。 示例 1&#xff1a; 输入&#xff1a;root [1,2,3,null,5]…

电器展示预约小程序的效果

大小电器是人们生活中必备的&#xff0c;电商经济条件下&#xff0c;很多消费者往往会通过线上购买电器&#xff0c;使得线下商家经营困难&#xff0c;但实体店依然有存在的意义&#xff0c;比如一些大件或精细电器&#xff0c;也需要亲自挑选、本地配送等。 对实体店商家来说…

云上智能驾驶三维重建优秀实践

本文重点介绍火山引擎多媒体实验室三维重建技术在动态、静态场景的以及结合先进光场重建技术的原理与实践&#xff0c;帮助大家能更好的了解和认识云上智能三维重建如何服务智能驾驶领域&#xff0c;助力行业发展。 智能驾驶技术的不断发展&#xff0c;正在改变着我们的出行方式…

【深入探究人工智能】历史、应用、技术与未来

深入探究人工智能 前言人工智能的历史人工智能的应用人工智能的技术人工智能的未来当代的人工智能产物结语&#x1f340;小结&#x1f340; &#x1f389;博客主页&#xff1a;小智_x0___0x_ &#x1f389;欢迎关注&#xff1a;&#x1f44d;点赞&#x1f64c;收藏✍️留言 &am…

第二十一章 模板

一、模板 1、模板的概念 模板就是建立通用的模具&#xff0c;大大提高复用性 例如生活中的模板 一寸照片模板&#xff1a; PPT模板&#xff1a; 模板的特点&#xff1a; 模板不可以直接使用&#xff0c;它只是一个框架 模板的通用并不是万能的 2、函数模板 C另一种编程思…

定时器和Timer

♫什么是定时器 定时器是一种计时设备&#xff0c;通过定时器可以让某段代码达到设定的时间后再执行。定时器是一个常用的组件&#xff0c;如在进行网络编程时就常用定时器来定时重发数据包、定时检测网络连接状态、定时更新缓存等操作。 ♫实现一个定时器 定时器需要有一个优先…