【一天一大 lee】填充每个节点的下一个右侧节点指针 (难度:中等) - Day20201015

20201015

题目:

给定一个完美二叉树,其所有叶子节点都在同一层,每个父节点都有两个子节点。二叉树定义如下:

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}

提示:

  1. 你只能使用常量级额外空间。
  2. 使用递归解题也符合要求,本题中递归程序占用的栈空间不算做额外的空间复杂度。

抛砖引玉

思路

题目中给定限制二叉树及二叉子树根节点都会有左右子节点,要求构建同层的 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 栏目
欢迎关注留言

公众号:前端小书童

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值