「这是我参与2022首次更文挑战的第24天,活动详情查看:2022首次更文挑战」。
题目
链接:leetcode-cn.com/problems/po…
给定一个 **完美二叉树 **,其所有叶子节点都在同一层,每个父节点都有两个子节点。二叉树定义如下:
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指针不断连接
var connect = function(root) {
if(root === null) return root
const stack = [root]
//每次出栈一层入栈一层,直至全部出栈完成全部遍历链接
while(stack.length){
//存一下现有栈的长度,即为本层的元素个数
const count = stack.length
for(let i = 0; i < count; i++){
//提取出栈的第一个元素并删除
element = stack.shift()
//提取出的元素与现在栈的第一个元素相连,即为同层链接
if(i < count -1) element.next = stack[0]
//将下一层的元素放入栈中
if(element.left != null) stack.push(element.left)
if(element.right != null) stack.push(element.right)
}
}
return root
};
指针分类
var connect = function(root) {
if(root === null) return root
//设定每层最左侧的元素lvLeft
let lvLeft = root
//保证lvLeft.left不为null,逐层遍历两种next指针
while(lvLeft.left){
//为了保证外循环参数lvLeft不受影响,设定内循环参数loopLeft
let loopLeft = lvLeft
while(loopLeft){
//第一种next指针,拥有同个父节点
loopLeft.left.next = loopLeft.right
//第二种next指针,从父节点的right指向父节点next的left
if(loopLeft.next){
loopLeft.right.next = loopLeft.next.left
}
//父节点推进
loopLeft = loopLeft.next
}
//每次向下一层
lvLeft = lvLeft.left
}
return root
};
dfs递归
学习了一下大佬的做法,不断深入最中间的连接,也就是指针分类方法中的第二种指针
在每次dfs中,连接两个父节点后,向下推进,连接左节点的右孩子和右节点的左孩子
直至二叉树的尽头,然后开始dfs左节点的左孩子,和右节点的右孩子
var connect = function(root) {
dfs(root)
return root
}
const dfs = (root) => {
if(root === null) return
let left = root.left
let right = root.right
while(left) {
left.next = right
left = left.right
right = right.left
}
dfs(root.left)
dfs(root.right)
}