LeetCode117-填充每个节点的下一个右侧节点指针 II
题目
给定一个二叉树
struct Node {
int val;
Node *left;
Node *right;
Node *next;
}
填充它的每个 next 指针,让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点,则将 next 指针设置为 NULL。
初始状态下,所有 next 指针都被设置为 NULL。
解法
方法一:层次遍历
方法二:递归,使用常数级额外空间
在方法一中,因为对树的结构一无所知,所以使用队列保证有序访问同一层的所有节点,并建立它们之间的连接。然而不难发现:一旦在某层的节点之间建立了 next 指针,那这层节点实际上形成了一个链表。因此,如果先去建立某一层的 next 指针,再去遍历这一层,就无需再使用队列了。
class Solution {
public Node connect(Node root) {
if(root==null) return null;
if(root.left!=null&&root.right!=null) {
root.left.next = root.right;
}
if(root.left!=null&&root.right==null) {
root.left.next = getNext(root.next);
}
if(root.right!=null) {
root.right.next = getNext(root.next);
}
// 这里要先遍历右子结点然后再遍历左子结点
// 先确保 root.right 下的节点的已完全连接,因 root.left 下的节点的连接
// 需要 root.left.next 下的节点的信息,若 root.right 下的节点未完全连
// 接(即先对 root.left 递归),则 root.left.next 下的信息链不完整,将
// 返回错误的信息。可能出现的错误情况如下图所示。此时,底层最左边节点将无
// 法获得正确的 next 信息:
// o root
// / \
// root.left o —— o root.right
// / / \
// o —— o o
// / / \
// o o o
connect(root.right);
connect(root.left);
return root;
}
private Node getNext(Node root){
if(root==null) return null;
if(root.left!=null) return root.left;
if(root.right!=null) return root.right;
if(root.next!=null) return getNext(root.next);
return null;
}
}
先递归左子树的一个反例:
上图中,若先递归左子树,则进行到7点右子树0点时候,getNext获得的是一个null,因为先递归的左子树,当进行到这个点的时候,7的next结点(9)还没进行递归,所以,会导致链接失败,所以应该先递归右子树。