填充每个节点的右侧节点指针1
给定一个完美二叉树,其所有叶子节点都在同一层,每个父节点都有两个子节点。二叉树定义如下:
struct Node {
int val;
Node *left;
Node *right;
Node *next;
}
填充它的每个 next 指针,让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点,则将 next 指针设置为 NULL。
初始状态下示例,所有 next 指针都被设置为 NULL。
思路1:广度优先遍历
1先判空
2..广度优先遍历需要队列,将根节点入队
3.队不空时,出队首,保证该节点依次指向队列中的节点0<=i<queue.size-1
4.依次判断出队节点的左右孩子是否存在,若存在依次入队,每次size大小(每层节点个数)会变化
import java.util.LinkedList;
/**
* Definition for binary tree with next pointer.
* public class TreeLinkNode {
* int val;
* TreeLinkNode left, right, next;
* TreeLinkNode(int x) { val = x; }
* }
*/
public class Solution {
public void connect(TreeLinkNode root) {
if(root==null){
return ;
}
LinkedList<TreeLinkNode> queue=new LinkedList<>();
queue.add(root);
while(queue.size()>0){
int size=queue.size();
for(int i=0;i<size;i++){
TreeLinkNode node=queue.poll();
if(i<size-1){
node.next=queue.peek();
}
if(node.left!=null) queue.add(node.left);
if(node.right!=null) queue.add(node.right);
}
}
}
}
思路二:使用已建立的next指针
1.判空
2.当完美二叉树左孩子为空说明结束
3.head记录树节点,head不空分两种情况分配next指针
4.情况一:同一父节点(head不空)
5.情况二:不同父节点(保证head.next不空)
6.结束同一层遍历head=head.next
7.进入下一层:leftmost=leftmost.next
/**
* Definition for binary tree with next pointer.
* public class TreeLinkNode {
* int val;
* TreeLinkNode left, right, next;
* TreeLinkNode(int x) { val = x; }
* }
*/
public class Solution {
public void connect(TreeLinkNode root) {
if(root==null){
return;
}
TreeLinkNode leftmost=root;
//完美二叉树没有左孩子说明结束啦
while(leftmost.left!=null){
TreeLinkNode head=leftmost;//head工作节点
//head.next不空说明还有节点
while(head!=null){
//情况一:同一父节点
head.left.next=head.right;
//情况二:不同父节点,head是否有右节点
if(head.next!=null){
head.right.next=head.next.left;
}
//同一层节点后移
head=head.next;
}
//进入到下一层节点
leftmost=leftmost.left;
}
}
}
填充每个节点的右侧节点指针2
如果给定的树可以是任意的二叉树呢?你之前的给出的算法还有效吗?
注意:
你只能使用常量的额外内存空间
解题思路:使用已建立的指针
一旦在某层的节点之间建立了 next 指针,那这层节点实际上形成了一个链表。基于该想法,提出降低空间复杂度的思路:
第 N 层节点之间建立 next 指针后,再建立第 N+1 层节点的 next 指针。因为可以通过 next 指针访问同一层的所有节点,所以使用第 N 层的 next 指针可以为第 N+1 层节点建立 next 指针。
1.从根节点开始。因为第 0 层只有一个节点,不需要处理。可以在上一层为下一层建立 next 指针。该方法最重要的一点是:位于第 N−1 层时为第 N 层建立 next 指针。一旦完成这些连接操作,移至第 N 层为第 N+1 层建立 next 指针。
2.当遍历到某层节点时,该层节点的 next 指针已经建立。这样就不需要队列从而节省空间。每次只要知道下一层的最左边的节点,就可以从该节点开始,像遍历链表一样遍历该层的所有节点。
/**
* Definition for binary tree with next pointer.
* public class TreeLinkNode {
* int val;
* TreeLinkNode left, right, next;
* TreeLinkNode(int x) { val = x; }
* }
*/
public class Solution {
TreeLinkNode leftmost;
TreeLinkNode pre;
//处理下一层节点
public void processchild(TreeLinkNode child){
if(child!=null){
//pre不空说明已经处理节点的下一层至少有一个孩子节点
if(pre!=null){
this.pre.next=child;
}else{
//pre为空说明下一层没有节点,child是第一个节点,所以更新leftmost,
this.leftmost=child;
}
//更新pre
this.pre=child;
}
}
//处理该层节点
public void connect(TreeLinkNode root) {
if(root==null){
return;
}
this.leftmost=root;//每层最左节点
TreeLinkNode cur=leftmost;//当前处理节点的本层
//如果leftmost结束说明整体结束
while(this.leftmost!=null){
cur=this.leftmost;//本层最新节点
this.pre=null;//
this.leftmost=null;//循环出口,如果没有孩子节点就可以结束了
while(cur!=null){
//处理该节点的左右孩子,处理下一层节点
this.processchild(cur.left);
this.processchild(cur.right);
//访问该层下一个节点
cur=cur.next;
}
}
}
}