LeetCode Notes_#117_填充每个节点的下一个右侧节点指针 II

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:层序遍历

解答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)

posted @ 2020-08-06 17:54  Howfar's  阅读(150)  评论(0)    收藏  举报