LeetCode Notes_#117_填充每个节点的下一个右侧节点指针 II
Contents
题目
给定一个二叉树
struct Node {
int val;
Node *left;
Node *right;
Node *next;
}
填充它的每个 next 指针,让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点,则将 next 指针设置为 NULL。
初始状态下,所有 next 指针都被设置为 NULL。
进阶:
- 你只能使用常量级额外空间。
- 使用递归解题也符合要求,本题中递归程序占用的栈空间不算做额外的空间复杂度。
示例:
提示:
- 树中的节点数小于 6000
- -100 <= node.val <= 100
思路分析
方法1:层序遍历
跟上一题LeetCode Notes_#116_填充每个节点的下一个右侧节点指针完全一样,不需要改动就可以通过。这里就不再写了。
方法2:利用已有的next指针
参考了这个题解。
跟LeetCode Notes_#116不同的是,这一题输入的二叉树不一定是完美二叉树,有很多节点是null
,那么之前的代码就行不通了。
主要的问题有两个(可以对照LeetCode Notes_#116理解):
- 外层循环,遍历所有层的时候,
leftmost
指针没法更新,也就是无法获取下一层的第一个节点。- 利用一个哑节点
dummy
,作为每一层链表的入口,- 在内层循环开始前定义
dummy
,作为下一层的开头 - 在内层循环中以
dummy
作为起点,向后连接各个节点 - 内层循环结束后,
cur
指向下一层的开头,也就是dummy.next
- 在内层循环开始前定义
- 利用一个哑节点
- 内层循环,连接某一层所有节点的时候,两个节点中间可能被
null
节点隔开(比如题目示例图中的节点5和7),所以无法用116题当中的“两种类型的连接”的方法去连接每个节点。- 增加条件判断,只有非
null
的节点会被连接到dummy
之后。
- 增加条件判断,只有非
具体涉及到了3个指针,如上图:
cur
:指向当前层当中访问到的节点dummy
:dummy.next
指向下一层的开头tail
:指向下一层的结尾,tail是不断更新的,每次加入一个新节点,tail就指向这个最后加入的节点。
解答
解答1:层序遍历
解答2:利用已有的next指针
class Solution {
public Node connect(Node root) {
Node cur = root;
//外层循环,遍历所有的层
while(cur != null){
//哑节点,不属于链表,但是可以充当链表的“入口”,dummy.next指向链表头节点
Node dummy = new Node();
//从dummy开始连接一层当中的节点
Node tail = dummy;
//内层循环,遍历一层中的所有节点,连接的是下一层的节点
while(cur != null){
if(cur.left != null){
tail.next = cur.left;
tail = tail.next;
}
if(cur.right != null){
tail.next = cur.right;
tail = tail.next;
}
cur = cur.next;
}
//dummy.next是下一层中的第一个节点
cur = dummy.next;
}
return root;
}
}
复杂度分析
时间复杂度:O(n)
空间复杂度:O(1)