首页   注册   登录
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Acceml
V2EX  ›  程序员

[Leetcode] 116. 填充同一层的兄弟节点

  •  
  •   Acceml · 282 天前 · 523 次点击
    这是一个创建于 282 天前的主题,其中的信息可能已经有所发展或是发生改变。

    题目

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

    struct Node { int val; Node *left; Node *right; Node *next; } 填充它的每个 next 指针,让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点,则将 next 指针设置为 NULL。

    初始状态下,所有 next 指针都被设置为 NULL。

    示例:

    image

    输入:{"$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}
    
    解释:给定二叉树如图 A 所示,你的函数应该填充它的每个 next 指针,以指向其下一个右侧节点,如图 B 所示。
    

    题解

    方法一: 层序遍历

    使用层序遍历,遍历的时候把同层的节点连接起来;

    image image

    class Solution {
        public Node connect(Node root) {
            if (root == null) return null;
            Queue<Node> queue = new LinkedList<>();
            queue.add(root);
            while (!queue.isEmpty()) {
                int size = queue.size();
                Node current = null;
                while (size > 0) {
                    Node node = queue.poll();
                    if (node.right != null) queue.add(node.right);
                    if (node.left != null) queue.add(node.left);
                    node.next = current;
                    current = node;
                    size--;
                }
            }
            return root;
        }
    }
    
    

    方法二:递归

    递归的时候我们通常就分解为递归子问题和递归结束条件。

    递归子问题

    • 左右子树分别连起来

    递归结束条件

    • node == null, 直接返回
    • node.left != null, 把 left.next 连到 node.right
    • node.right != null && node.next != null, 把 node 的 right 连到 node.next 的 left。例如遍历到 2 这个节点,把 5 连接到 6. image.png

    image.png

    class Solution {
        public Node connect(Node root) {
            // o(1) space.
            if (root == null) return null;
            if (root.left != null) root.left.next = root.right;
            if (root.right != null && root.next != null) root.right.next = root.next.left;
            connect(root.left);
            connect(root.right);    
            return root;
        }
    }
    

    方法三: 层序遍历 o(1)空间复杂度

    层序遍历我们之前用队列来做,但是有时候我们会要求层序遍历用常数的空间复杂度来解。这种方法最关键的地方在于理解如何从上一层切换到下一层的。dummy 的作用用于记录上一层的第一个节点是谁,每当遍历完一层之后,切到下一层. image

    class Solution {
        public Node connect(Node root) {
            Node dummy = new Node(0);
            Node pre = dummy;
            Node currentRoot = root;
            while (currentRoot != null) {
                if (currentRoot.left != null) {
                    pre.next = currentRoot.left;
                    pre = pre.next;
                }
                if (currentRoot.right != null) {
                    pre.next = currentRoot.right;
                    pre = pre.next;
                }
                currentRoot = currentRoot.next;
                if (currentRoot == null) {
                    // 切换层.
                    pre = dummy;
                    currentRoot = dummy.next;
                    dummy.next      = null;
                }
            }
            return root;
        }
    }
    

    热门阅读

    Leetcode 名企之路

    目前尚无回复
    关于   ·   FAQ   ·   API   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   2247 人在线   最高记录 5168   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.3 · 23ms · UTC 07:00 · PVG 15:00 · LAX 23:00 · JFK 02:00
    ♥ Do have faith in what you're doing.