Populating Next Right Pointers in Each Node II

https://leetcode.com/problems/populating-next-right-pointers-in-each-node-ii/

Follow up for problem "Populating Next Right Pointers in Each Node".

What if the given tree could be any binary tree? Would your previous solution still work?

Note:

  • You may only use constant extra space.

 

For example,
Given the following binary tree,

         1

       /  \

      2    3

     / \    \

    4   5    7

 

After calling your function, the tree should look like:

         1 -> NULL

       /  \

      2 -> 3 -> NULL

     / \    \

    4-> 5 -> 7 -> NULL

解题思路:

先给出一个level order traversal的方法,虽然不符合题目要求的constant space,不过贵在简单。

这种在层次遍历时要求区分每层,在每层内做操作的题目已经出现好多了,方法就是用一个变量去存当前层次的size。下面多出的两个问题,第一,用两个指针指向同一层次的前后两个节点,把前面节点的next指向后面的即可。第二,遇到最后一个节点,这里用levelSize == 0来判断,next指向null。

/**

 * 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) {

        Queue<TreeLinkNode> queue = new LinkedList<TreeLinkNode>();

        if(root == null){

            return;

        }

        queue.offer(root);

        while(queue.size() != 0){

            int levelSize = queue.size();

            TreeLinkNode preNode = null;

            while(levelSize > 0){

                TreeLinkNode currentNode = queue.poll();

                if(currentNode.left != null){

                    queue.offer(currentNode.left);

                }

                if(currentNode.right != null){

                    queue.offer(currentNode.right);

                }

                //层序遍历,本层前一个node指向后一个node

                if(preNode != null){

                    preNode.next = currentNode;

                }

                preNode = currentNode;

                levelSize--;

                //本层最后一个node指向null

                if(levelSize == 0){

                    currentNode.next = null;

                }

            }

        }

    }

}

下面考虑题目的要求,使用constant space。上一个问题Populating Next Right Pointers in Each Node中,将root.left.next设置为root.right,root.right.next设置为root.next.left。这里由于不是一个完全二叉树,左右子树都有可能为空。所以只有在root.right !=null的时候,root.left.next才能置为root.right。否则就需要看root右侧的节点,即root.next的左右子树。如果root.next不为空,但是它的左右子树都是空的,就再向右看。

处理root.right也是一样的道理。

需要注意的是递归的顺序,必须先递归右子树,再递归左子树。如果反过来的话,右子树还未处理,这样root.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;

        }

        if(root.left != null){

            if(root.right != null){

                root.left.next = root.right;

            }else{

                TreeLinkNode next = root.next;

                //如果next不为null,但都没有左右子树,则继续往右取next

                while(next != null && next.left == null && next.right == null){

                    next = next.next;

                }

                if(next == null){

                    root.left.next = null;

                }else{

                    if(next.left != null){

                        root.left.next = next.left;

                    }else{

                        if(next.right != null){

                            root.left.next = next.right;

                        }

                    }

                }

            }

        }

        if(root.right != null){

            TreeLinkNode next = root.next;

            while(next != null && next.left == null && next.right == null){

                next = next.next;

            }

            if(next == null){

                root.right.next = null;

            }else{

                if(next.left != null){

                    root.right.next = next.left;

                }else{

                    if(next.right != null){

                        root.right.next = next.right;

                    }

                }

            }

        }

        //必须先处理右子树,再处理左子树。否则可能此时root.next还未赋值,还是null

        connect(root.right);

        connect(root.left);

    }

}

下面将这个解法改成迭代。处理具体节点的方法不变,无非就是循环的条件。

这里,每一层root都用root.next去迭代它,每层循环终止的条件是,root==null。这时去找下一层的第一个节点,如何找?在该层中,找到第一个本身不为空,而且有左子树或者右子树的节点,将它的左子树或者右子树作为下一层的第一个节点。然后进入内层循环处理该层。

外层循环结束的条件是,找不到下一层的处理节点,即下一层的第一个节点为null。

/**

 * 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 nextLevelHead = root;

        

        while (nextLevelHead != null) {

            while (root != null) {

                if (root.left != null) {

                    if (root.right != null) {

                        root.left.next = root.right;

                    } else {

                        TreeLinkNode next = root.next;

                        //如果next不为null,但都没有左右子树,则继续往右取next

                        while (next != null && next.left == null && next.right == null) {

                            next = next.next;

                        }

                        if (next == null) {

                            root.left.next = null;

                        } else {

                            if (next.left != null) {

                                root.left.next = next.left;

                            } else {

                                if (next.right != null) {

                                    root.left.next = next.right;

                                }

                            }

                        }

                    }

                }

                if (root.right != null) {

                    TreeLinkNode next = root.next;

                    while (next != null && next.left == null && next.right == null) {

                        next = next.next;

                    }

                    if (next == null) {

                        root.right.next = null;

                    } else {

                        if (next.left != null) {

                            root.right.next = next.left;

                        } else {

                            if (next.right != null) {

                                root.right.next = next.right;

                            }

                        }

                    }

                }

                root = root.next;

            }

            

            //root.next已经为null,寻找下一层的头节点。道理同上,一直往右找到有左右子树的节点作为root

            while (nextLevelHead != null && nextLevelHead.left == null && nextLevelHead.right == null) {

                nextLevelHead = nextLevelHead.next;

            }

            if(nextLevelHead == null){

                return;

            }

            if (nextLevelHead.left != null) {

                nextLevelHead = nextLevelHead.left;

            } else {

                nextLevelHead = nextLevelHead.right;

            }

            root = nextLevelHead;

        }

    }

}

update 2015/05/17:

上面的解法都是寻找当前节点next指向的下一个节点,所以要循环获取。

改变一下思路,保存上一节点pre,遇见当前节点,将pre.next指向当前不就行了?这样一来,代码极为简化。pre和nextLevelFirst就取当前层次中,第一个非null的就可以。想到这个思路,是因为这个题目其实就是类似链表,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 nextLevelFirst = root.left;

        if(nextLevelFirst == null) {

            nextLevelFirst = root.right;

        }

        TreeLinkNode pre = null;

        while(root != null) {

            if(root.left != null) {

                if(nextLevelFirst == null) {

                    nextLevelFirst = root.left;

                }

                if(pre != null) {

                    pre.next = root.left;

                    pre = root.left;

                } else {

                    pre = root.left;

                }

            }

            if(root.right != null) {

                if(nextLevelFirst == null) {

                    nextLevelFirst = root.right;

                }

                if(pre != null) {

                    pre.next = root.right;

                    pre = root.right;

                } else {

                    pre = root.right;

                }

            }

            if(root.next != null) {

                root = root.next;

            } else {

                root = nextLevelFirst;

                nextLevelFirst = null;

                pre = null;

            }

        }

    }

}

 

你可能感兴趣的:(right)