[LeetCode] Populating Next Right Pointers in Each Node 每个节点的右向指针

 

Given a binary tree

    struct TreeLinkNode {
      TreeLinkNode *left;
      TreeLinkNode *right;
      TreeLinkNode *next;
    }

 

Populate each next pointer to point to its next right node. If there is no next right node, the next pointer should be set to NULL.

Initially, all next pointers are set to NULL.

Note:

  • You may only use constant extra space.
  • You may assume that it is a perfect binary tree (ie, all leaves are at the same level, and every parent has two children).

 

For example,
Given the following perfect binary tree,

         1
       /  \
      2    3
     / \  / \
    4  5  6  7

 

After calling your function, the tree should look like:

         1 -> NULL
       /  \
      2 -> 3 -> NULL
     / \  / \
    4->5->6->7 -> NULL

这道题实际上是树的层序遍历的应用,可以参考之前的博客Binary Tree Level Order Traversal 二叉树层序遍历,既然是遍历,就有递归和非递归两种方法,最好两种方法都要掌握,都要会写。下面先来看递归的解法,由于是完全二叉树,所以若节点的左子结点存在的话,其右子节点必定存在,所以左子结点的next指针可以直接指向其右子节点,对于其右子节点的处理方法是,判断其父节点的next是否为空,若不为空,则指向其next指针指向的节点的左子结点,若为空则指向NULL,代码如下:

 

// Recursion, more than constant space
class Solution {
public:
    void connect(TreeLinkNode *root) {
        if (!root) return;
        if (root->left) root->left->next = root->right;
        if (root->right) root->right->next = root->next? root->next->left : NULL;
        connect(root->left);
        connect(root->right);
    }
};

 

对于非递归的解法要稍微复杂一点,但也不算特别复杂,需要用到queue来辅助,由于是层序遍历,每层的节点都按顺序加入queue中,而每当从queue中取出一个元素时,将其next指针指向queue中下一个节点即可。代码如下:

 

// Non-recursion, more than constant space
class Solution {
public:
    void connect(TreeLinkNode *root) {
        if (!root) return;
        queue<TreeLinkNode*> q;
        q.push(root);
        q.push(NULL);
        while (true) {
            TreeLinkNode *cur = q.front();
            q.pop();
            if (cur) {
                cur->next = q.front();
                if (cur->left) q.push(cur->left);
                if (cur->right) q.push(cur->right);
            } else {
                if (q.size() == 0 || q.front() == NULL) return;
                q.push(NULL);
            }
        }
    }
};

 

以上两种方法虽然能通过OJ检测,但是由于OJ没有检测空间复杂度,而题目要求constant space,明显上面两种解法都不符合要求。下面贴上constant space的解法,这个算法的思路是先定义一个leftMost指针用来指向当前行最左边的一个,由于是完全树,所以指向左子结点,然后还要记录上一层中的父节点,再需要一个cur指针指向当前层遍历到的节点,左子结点的next指针之间赋给右子节点,那么当cur到右子节点时,需要把上一层的父节点向右移到新的父节点(如果存在的话),然后把当前cur的next赋给新的父节点的左子结点,以此类推,完成所有的next复制,代码如下:

 

class Solution {
public:
    void connect(TreeLinkNode *root) {
        if (!root) return;
        TreeLinkNode *leftMost = root;
        while (leftMost) {
            TreeLinkNode *p = leftMost;
            if (!p->left) return;
            leftMost = p->left;
            TreeLinkNode *cur = leftMost;
            while (p) {
                if (cur == p->left) {
                    cur->next = p->right;
                    cur = cur->next;
                    p = p->next;
                } else {
                    cur->next = p->left;
                    cur = cur->next;
                }
            }
        }
    }
};

 

LeetCode All in One 题目讲解汇总(持续更新中...)

你可能感兴趣的:(LeetCode)