116. Populating Next Right Pointers in Each Node (Medium)

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. $$O(1)$$
  • 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

Solution 1: Tree, level traverse, BFS

Time Complexity: $$O(n)$$
Space Complexity: $$O(n)$$

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

version 1: 23ms

每一层都存一个NULL在结尾,方便next指针。

/**
 * Definition for binary tree with next pointer.
 * struct TreeLinkNode {
 *  int val;
 *  TreeLinkNode *left, *right, *next;
 *  TreeLinkNode(int x) : val(x), left(NULL), right(NULL), next(NULL) {}
 * };
 */
class Solution {
public:
    void connect(TreeLinkNode *root) {
        if (!root) return;
        queue<TreeLinkNode*> q;
        q.push(root); 
        q.push(NULL);
        while (q.size() > 1) {
            int size = q.size()-1;
            for (int i = 0; i < size; ++i) {
                TreeLinkNode* cur = q.front(); q.pop();
                cur->next = q.front();
                if (cur->left) {
                    q.push(cur->left);
                    q.push(cur->right);
                }
            }
            q.pop(); // pop NULL in last level;
            q.push(NULL);
        }
    }
};

version 2: 19ms

用vector

class Solution {
public:
    void connect(TreeLinkNode *root) {
        if (!root) return;
        vector<TreeLinkNode*> level;
        level.push_back(root);
        while (!level.empty()) {
            vector<TreeLinkNode*> tmp;
            for (int i = 0; i < level.size(); ++i) {
                level[i]->next = (i+1 < level.size()) ? level[i+1]:NULL;

                if (level[i]->left) {
                    tmp.push_back(level[i]->left);
                    tmp.push_back(level[i]->right);
                }
            }
            swap(level,tmp);
        }
    }
};

Solution 2: recursive, DFS

Time Complexity: $$O(n)$$
Space Complexity: $$O(n)$$

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

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

Solution 3:

Time Complexity: $$O(n)$$
Space Complexity: $$O(1)$$

上面三种方法虽然叼,但是都不符合题意,题目中要求用O(1)的空间复杂度,所以我们来看下面这种碉堡了的方法。用两个指针start和cur,其中start标记每一层的起始节点,cur用来遍历该层的节点,设计思路之巧妙,不得不服啊:

class Solution {
public:
    void connect(TreeLinkNode *root) {
        if (!root) return;
        // start: points to the start of each level
        TreeLinkNode* start = root, *cur = NULL;
        while (start->left) {
            cur = start;
            while (cur) {
                cur->left->next = cur->right;
                if (cur->next) cur->right->next = cur->next->left;
                cur = cur->next;
            }
            start = start->left;
        }
    }
};

Solution 4: Hash Table

results matching ""

    No results matching ""