二叉树4. 层次遍历之三:下一个右侧节点指针
Posted 纵横千里,捭阖四方
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了二叉树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;
}
以上是关于二叉树4. 层次遍历之三:下一个右侧节点指针的主要内容,如果未能解决你的问题,请参考以下文章
116. 填充每个节点的下一个右侧节点指针 二叉树 逆序BFS O(n)/ 利用 father.next遍历下层节点 O
LeetCode 二叉树专项填充每个节点的下一个右侧节点指针(116)