题目:
给定一个完美二叉树,其所有叶子节点都在同一层,每个父节点都有两个子节点。二叉树定义如下:
struct Node {
int val;
Node *left;
Node *right;
Node *next;
}
填充它的每个 next 指针,让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点,则将 next 指针设置为 NULL。
初始状态下,所有 next 指针都被设置为 NULL。
输入:{"$id":"1","left":{"$id":"2","left":{"$id":"3","left":null,"next":null,"right":null,"val":4},"next":null,"right":{"$id":"4","left":null,"next":null,"right":null,"val":5},"val":2},"next":null,"right":{"$id":"5","left":{"$id":"6","left":null,"next":null,"right":null,"val":6},"next":null,"right":{"$id":"7","left":null,"next":null,"right":null,"val":7},"val":3},"val":1}
输出:{"$id":"1","left":{"$id":"2","left":{"$id":"3","left":null,"next":{"$id":"4","left":null,"next":{"$id":"5","left":null,"next":{"$id":"6","left":null,"next":null,"right":null,"val":7},"right":null,"val":6},"right":null,"val":5},"right":null,"val":4},"next":{"$id":"7","left":{"$ref":"5"},"next":null,"right":{"$ref":"6"},"val":3},"right":{"$ref":"4"},"val":2},"next":null,"right":{"$ref":"7"},"val":1}
提示:
- 你只能使用常量级额外空间。
- 使用递归解题也符合要求,本题中递归程序占用的栈空间不算做额外的空间复杂度。
抛砖引玉
思路
题目中给定限制二叉树及二叉子树根节点都会有左右子节点,要求构建同层的 next 指针
换个方式理解就是要求按层遍历二叉树,然后同层构建 next
按层遍历二叉树的题目之前做过:二叉树的层次遍历 II
BFS 的逻辑本身就是优先按层级遍历则,本题自然想到使用 BFS
广度优先搜索(BFS)
一层层构建 next
/**
* // Definition for a Node.
* function Node(val, left, right, next) {
* this.val = val === undefined ? null : val;
* this.left = left === undefined ? null : left;
* this.right = right === undefined ? null : right;
* this.next = next === undefined ? null : next;
* };
*/
/**
* @param {Node} root
* @return {Node}
*/
var connect = function(root) {
let queue = [root]
if (root == null) return []
while (queue.length) {
// len是上一层节点数量
let len = queue.length
for (let i = 0; i < len; i++) {
let node = queue.shift()
// 最后一个不用更新next
if (i < len - 1) node.next = queue[0]
if (node.left) {
queue.push(node.left)
}
if (node.right) {
queue.push(node.right)
}
}
}
return root
}
深度优先搜索(DFS)
遍历二叉树常用的方式还有 DFS
深度优先搜索的逻辑是利用递归,一个子树一个子树的数量,直到遇到叶子节点(不存在左右节点的节点)终止递归
DFS 模板:
function dfs(node) {
if (node == null) return
if (node.left) dfs(node.left)
if (node.right) dfs(node.right)
}
因为题目限制了二叉树及二叉子树根节点都会有左右子节点,那么:
- 当递归中传入一个节点时(1),其 left 节点的 next 指针直接指向其 right 节点(2->3)
- 既然构建了子节点的链接(2->3)那么后续构建 next 可以借助已经构建的 next:
如果传入节点有 next 那么其 right 节点的 next 指针将指向其 next 节点的 left 节点
var connect = function(root) {
if (root == null) return root
dfs(root)
function dfs(node) {
if (node.left == null || node.left == null) return
node.left.next = node.right
if (node.next != null) {
node.right.next = node.next.left
}
if (node.left) dfs(node.left)
if (node.right) dfs(node.right)
}
return root
}
博客: 前端小书童
每天的每日一题,写的题解会同步更新到公众号一天一大 lee 栏目
欢迎关注留言