首页 > 代码库 > [C++]LeetCode: 123 Populating Next Right Pointers in Each Node(链接完全二叉树)

[C++]LeetCode: 123 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

Answer 1: 使用队列

思路:我们维护一个前序节点和队列。队列用于把遍历到的节点压入队列,每次从队列中取出一个节点,如果前序节点非空,我们链接前序节点和当前节点,更新前序节点为当前节点。判断当前节点是否为NULL,如果是,则说明到达本层的最后,我们用NULL来区分每一层。注意只有在队列非空时,我们才加入层的区分标志NULL,否则在树的最后一层会造成死循环。

这种办法虽然AC 可是使用了队列来存储节点,空间复杂度是O(lg(N))。没有达到最优,下一种方法介绍一个O(1)的方法

Attention:

1. 如何连接前序节点和当前节点。

if(pre != NULL)
            {
                pre->next = node;
            }
            pre = node;
AC Code:
/**
 * 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) {
        queue<TreeLinkNode*> treeQ;
        if(root == NULL) return;
        treeQ.push(root);
        treeQ.push(NULL);
        TreeLinkNode* pre(NULL);
        
        while(!treeQ.empty())
        {
            TreeLinkNode* node = treeQ.front();
            treeQ.pop();
            
            if(pre != NULL)
            {
                pre->next = node;
            }
            pre = node;
            
            if(node != NULL)
            {
                if(node->left) treeQ.push(node->left);
                if(node->right) treeQ.push(node->right);
            }
            else
            {
                if(!treeQ.empty())
                {
                    treeQ.push(NULL);     //区分每层
                }
            }
        }
        return;
    }
};

Answer 2: 常数空间复杂度

思路:这道题是要求我们将一棵树的每一层维护成一个链表,树是给定的完全二叉树。这里我们其实不需要额外维护一个队列,因为这里每一层我们会维护成一个链表,可以从链表中得到下一个节点的信息。每一层链表的起点就是树每层最左的那个节点,也就是我们只需要维护一个链表的起始指针就可以依次得到整个队列了。我们维护两个节点指针,一个是每层队列的链表起始节点pre,一个是当前的根结点,用于连接它的孩子。如果当前节点不为空,说明还有孩子结点,还需要连接。我们根据题目要求连接孩子结点。一层结束后,我们更新pre为下一层的起始结点,即pre->left

复杂度:时间复杂度,对每个结点都要遍历一次,O(N), 空间不需要队列,O(1)

AC Code:

/**
 * 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 == NULL) return;
        TreeLinkNode* pre = root;  //pre维护着每一行的链表开始的根结点
        TreeLinkNode* cur = NULL;
        
        while(pre->left)
        {
            cur = pre;  //cur代表当前要链接的两个节点的根结点
            while(cur)
            {
                cur->left->next = cur->right;
                if(cur->next) cur->right->next = cur->next->left;  
                cur = cur->next; //cur跳到同行的下个根结点
            }
            pre = pre->left;
        }
    }
};



[C++]LeetCode: 123 Populating Next Right Pointers in Each Node(链接完全二叉树)