面试经典150题[074]:填充每个节点的下一个右侧节点指针 II(LeetCode 117)

填充每个节点的下一个右侧节点指针 II(LeetCode 117)

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

难度:中等

1. 题目描述

给你一个二叉树的根节点 root ,请你将其中所有节点的 next 指针指向其右侧的节点。如果没有右侧节点,则 next 指针应设置为 NULL

初始时,所有 next 指针都设置为 NULL

树节点定义:

python 复制代码
class Node:
    def __init__(self, val: int = 0, left: 'Node' = None, right: 'Node' = None, next: 'Node' = None):
        self.val = val
        self.left = left
        self.right = right
        self.next = next

要求:

  • 二叉树不一定是完美的(即不一定是满二叉树或完全二叉树)。
  • 节点数 0 <= n <= 6000
  • -100 <= Node.val <= 100

示例:

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

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

2. 问题分析

2.1 规律

  • 这是一个二叉树问题,需要将同一层的节点通过 next 指针连接起来,形成一个链表。
  • 与 LeetCode 116 不同,本题的树不一定是完美的,因此不能假设每层都有完整的左右子节点。
  • 核心问题:如何在不使用额外空间(如队列)的情况下,高效连接同一层节点?
  • 类似于层序遍历,但需要处理缺失节点的情况。

2.2 贪心思路

我们使用常量空间的层级连接方法:

  • 从根节点开始,逐层处理。
  • 对于每一层,使用一个虚拟节点 dummy 来构建下一层的链表头,并用 tail 指针来连接下一层的子节点。
  • 遍历当前层的节点(通过已连接的 next 指针),为每个节点的左右子节点建立连接:
    • 如果有左子节点,连接到 tail.next
    • 如果有右子节点,连接到 tail.next
  • 当前层遍历结束后,将下一层的头节点设置为 dummy.next,继续处理下一层。
  • 这个方法利用了上一层的 next 指针来遍历当前层,避免使用队列,实现 O(1) 额外空间。
  • 如果树为空或只有根节点,直接返回。

3. 代码实现

Python

python 复制代码
class Solution:
    def connect(self, root: 'Node') -> 'Node':
        if not root:
            return root
        
        head = root
        while head:
            dummy = Node(0)
            tail = dummy
            cur = head
            while cur:
                if cur.left:
                    tail.next = cur.left
                    tail = tail.next
                if cur.right:
                    tail.next = cur.right
                    tail = tail.next
                cur = cur.next
            head = dummy.next
        return root

C++

cpp 复制代码
class Solution {
public:
    Node* connect(Node* root) {
        if (!root) return root;
        
        Node* head = root;
        while (head) {
            Node* dummy = new Node(0);
            Node* tail = dummy;
            Node* cur = head;
            while (cur) {
                if (cur->left) {
                    tail->next = cur->left;
                    tail = tail->next;
                }
                if (cur->right) {
                    tail->next = cur->right;
                    tail = tail->next;
                }
                cur = cur->next;
            }
            head = dummy->next;
            // 注意:在C++中,需要手动删除dummy以避免内存泄漏,但LeetCode环境可忽略
        }
        return root;
    }
};

4. 复杂度分析

  • 时间复杂度:O(n),遍历每个节点一次。
  • 空间复杂度:O(1),只使用常量额外空间(不计递归栈或队列)。

5. 总结

  • 连接 next 指针问题 + 非完美二叉树 → 使用虚拟节点构建下一层链表是首选。
  • 核心维护 dummytail,很通用。
    • 类似于优化后的 BFS 层序遍历,但空间为 O(1)。
    • 可扩展到完美二叉树的变体(LeetCode 116)。

复习

面试经典150题014加油站(LeetCode 134)

面试经典150题044两数之和(LeetCode 1)

面试经典150题059合并两个有序链表(LeetCode 21)

相关推荐
小肝一下18 分钟前
3. 单链表
c语言·数据结构·c++·算法·leetcode·链表·dijkstra
tachibana234 分钟前
hot100 前 K 个高频元素(347)
java·数据结构·算法·leetcode
程序员爱钓鱼43 分钟前
Go 开发环境安装(Windows、macOS、Linux)
后端·面试·go
触底反弹1 小时前
🤯 面试被问 AI Workflow 和 Agent 有啥区别?3 张图 + 2 段代码讲清楚!
人工智能·设计模式·面试
uzong8 小时前
一个好的面试官,应该让候选人感到被尊重
面试
To_OC8 小时前
LC 131 分割回文串:刚学回溯时,我连怎么切字符串都想不明白
javascript·算法·leetcode
旖-旎10 小时前
LeetCode 518:零钱兑换||(完全背包)—— 题解
c++·算法·leetcode·动态规划·背包问题
To_OC10 小时前
LC 42 接雨水:暴力超时卡半天?前后缀数组一用就通了
javascript·算法·leetcode
触底反弹11 小时前
深入理解大模型采样:Temperature、Top-K、Top-P 的原理与实战
人工智能·算法·面试
沉默王二13 小时前
腾讯一面,我霸气反问:“你说你们在做Agent项目,说说 SubAgent、Plan 模式、Skill 调用这些你们都是怎么做的?”面试官一直在擦汗。。
面试·agent·ai编程