码迷,mamicode.com
首页 > 其他好文 > 详细

Populating Next Right Pointers in Each Node II

时间:2015-03-09 22:27:47      阅读:273      评论:0      收藏:0      [点我收藏+]

标签:

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;
        }
    }
}

 

Populating Next Right Pointers in Each Node II

标签:

原文地址:http://www.cnblogs.com/NickyYe/p/4323945.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!