这个题目和leetcode_116是类似的,但是这个题目不能其中的第二种解法,因为它并不是一个完全二叉树。但是第一种解法是可行的(原谅我第一种写法写的有点冗余,但是也不想改了,算是留着个教训吧)。
- 查看当前节点是父节点的左子节点还是右子节点。
- 如果是左子节点则查看右子节点是否为空:不为空则让左子节点的next指向右子节点;为空则顺着父节点的next指针向下找,直到找到一个有孩子节点的树,如果没找到这样的树则当前节点的next就为null,找到了则next指向其中的某个子节点(从左到右判断)。
- 如果是右子节点和第二种情况中右子节点为空的情况类似,即沿着父节点的next指针向下找。
这个地方有一个要注意的事项,就是当前节点改造完后,必须先对节点的右子树进行改造,然后才对节点的左子树进行改造。例如下面的例子,假如对根节点的左子树改造完后(即图中箭头1),然后继续向左,改造节点2的左子树(图中箭头2),然后继续向左改造节点4的左子树节点8,此时沿着父节点4的next指针只能到达节点5,最终导致节点8的next只能指向null。
如果先对右子树进行改造,那情况就不一样了。如图所示箭头上的数字代表next指针更改的顺序,因为先改造右子树,所以总能保证某个节点的父节点的next指针可以到达最右方。
完整代码如下:
public Node connect(Node root) {
if (root == null)
return;
helper(root, root.right); //先改造右子树
helper(root, root.left); //后改造左子树
return root;
}
private void helper(Node parent, Node root) {
if (root == null)
return;
if (parent.left == root) {
if(parent.right != null) //若当前节点是个左子节点,且兄弟不为null,则其next直接指向兄弟
root.next = parent.right;
else { //否则沿着父节点的next向下找
Node p = parent.next;
while (p != null && p.left == null && p.right == null) //找到一个有子节点的根节点
p = p.next;
if (p != null) //p不为空则从左往右取最近的,p为空则直接使用默认的null即可
root.next = p.left != null ? p.left : p.right;
}
} else { //是个右节点则直接沿着父节点的next指针向下找
Node p = parent.next;
while (p != null && p.left == null && p.right == null) //找到一个有子节点的根
p = p.next;
if (p != null) //p不为空则从左往右取最近的,p为空则直接使用默认的
root.next = p.left != null ? p.left : p.right;
}
helper(root, root.right); //先构造右子树
helper(root, root.left); //后构造左子树
}