二叉树4. 层次遍历之三:下一个右侧节点指针

现在我们来看两个递进的题目:

​116. 填充每个节点的下一个右侧节点指针

117.填充每个节点的下一个右侧节点指针I

1.LeetCode 116 填充满二叉树的下一个右侧节点指针

给定一个 完美二叉树 ,其所有叶子节点都在同一层,每个父节点都有两个子节点。填充它的每个 next 指针,让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点,则将 next 指针设置为 NULL。初始状态下,所有 next 指针都被设置为 NULL。

示例:

方法1:迭代解法

回想一下二叉树的层次遍历,用广度优先实现的时候,就是层层遍历,每层临时遍历的节点都会放到一个队列中。

队列中保存了第 i 层节点的信息,我们利用这个特点,将队列中的元素都串联一遍就可以了。

class Solution {  public Node connect(Node root) {    if(root==null) {      return root;    }    LinkedList<Node> queue = new LinkedList<Node>();    queue.add(root);    while(queue.size()>0) {      int size = queue.size();      //将队列中的元素串联起来      Node tmp = queue.get(0);      for(int i=1;i<size;++i) {        tmp.next = queue.get(i);        tmp = queue.get(i);      }      //遍历队列中的每个元素,将每个元素的左右节点也放入队列中      for(int i=0;i<size;++i) {        tmp = queue.remove();        if(tmp.left!=null) {          queue.add(tmp.left);        }        if(tmp.right!=null) {          queue.add(tmp.right);        }      }    }    return root;  }}

 方法2:迭代法2

题目要求是常量的辅助空间,所以第一种解法并不符合要求,下面来看下 O(1)空间复杂度的实现细节。

注意,题目说的二叉树是一棵完美二叉树,即每一层的节点都是满的。

仔细看下完成后的串联树,其连接的方式有两种:

第一种 是这两个串联的节点都有一个共同的父节点,通过父节点就可以将这两个子节点串联起来。

第二种 是这两个串联的节点的父节点不同,对于这种情况,如果我们能将这一层的上一层串联好。那么可以通过父节点的next找到邻居,完成串联。

即:

root.right.next => root.next.left

这里我们需要保证 root.next 不为空就可以了。

也就是说当我们要串联第 i 层节点时,需要先完成第 i-1 层的节点串联

第一层最多只有一个节点,不需要串联

第二层最多只有两个节点,借助根节点就可以完成串联了

第三层串联时,上一层已经串联完了,所以第三层可以完成串联

同理,可以完成第四层,第五层,第N层的串联

class Solution {  public Node connect(Node root) {    if(root==null) {      return root;    }    Node pre = root;    //循环条件是当前节点的left不为空,当只有根节点    //或所有叶子节点都出串联完后循环就退出了    while(pre.left!=null) {      Node tmp = pre;      while(tmp!=null) {        //将tmp的左右节点都串联起来        //注:外层循环已经判断了当前节点的left不为空        tmp.left.next = tmp.right;        //下一个不为空说明上一层已经帮我们完成串联了        if(tmp.next!=null) {          tmp.right.next = tmp.next.left;        }        //继续右边遍历        tmp = tmp.next;      }      //从下一层的最左边开始遍历      pre = pre.left;    }    return root;  }}

2.LeetCode117. 填充每个节点的下一个右侧节点指针 II

这个题与前面题的区别就是,树不是满二叉树,而是普通二叉树。

如图:

看到这句话,第一反应就是层序遍历,设置pre结点,将pre结点的next指向队列中的下一个节点即可。

思路:

根节点不为null,将根节点入队。并进入循环。

设置size表示当前层一共有多少个节点。

设置pre结点表示前一个结点。每从队列中出队一个结点,将pre的next指针指向出队结点。

pre结点后移。

判断如果有左右孩子,分别将左右孩子入队。

    public Node connect(Node root) {        Node tail = root;        Deque<Node> deque = new ArrayDeque<>();        if (tail != null) deque.addFirst(tail);        while (!deque.isEmpty()) {            int size = deque.size();            Node pre = null;            for (int i = 0; i < size; i++) {                if (pre == null) pre = deque.pollLast();                else {                    pre.next = deque.peekLast();                    pre = deque.pollLast();                }                if (pre.left != null) deque.addFirst(pre.left);                if (pre.right != null) deque.addFirst(pre.right);            }        }        return root;    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

纵横千里,捭阖四方

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值