首页 > 代码库 > 【leetcode】Populating Next Right Pointers in Each Node

【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

解法一,递归:

开始准备用队列的,结果空间溢出了,因为题目中要求常数空间。然后上网找到解决办法:递归。但是有一点我很疑惑,递归不是需要一个栈,虽然没有显示申明,但是也不是原地算法呀。

递归的思想如下:

碰到当前的根节点root:

1.如果有左子有右子,就把左子的next指向右子。

2.然后循环的把root左右两颗树之间的next设置好。例如下图中,循环结束后,root两颗子树之间的next就都设置好了

3. 递归调用connect解决左右子树内部的连接。

代码如下:

 1 /**
 2  * Definition for binary tree with next pointer.
 3  * struct TreeLinkNode {
 4  *  int val;
 5  *  TreeLinkNode *left, *right, *next;
 6  *  TreeLinkNode(int x) : val(x), left(NULL), right(NULL), next(NULL) {}
 7  * };
 8  */
 9 class Solution {
10 public:
11     void connect(TreeLinkNode *root) {
12         if(root == NULL)
13             return;
14         TreeLinkNode *l = root->left;
15         TreeLinkNode *r = root->right;
16         while(l != NULL){
17             l->next = r;
18             l = l->right;
19             r = r->left;
20         }
21         connect(root->left);
22         connect(root->right);
23     }
24 };

 


解法二:题目中要求原地算法,所以我们还是要想个办法把递归转换成循环。

这个算法是一层一层遍历的。最外层的大循环控制每一层的遍历,要遍历一层,我只要知道这一层的第一个节点以及在遍历这一层之前把这一层所有的节点通过“next”串起来就好了。

这一点可以通过第二层循环实现:

1. 在当下的节点为current时,首先看下一层的第一个节点first_node_next_layer这个指针是否为空,如果是,说明还没找到下一层的第一个节点,那么current->left必然是下一层的第一个节点;

2. 然后看current的左子是否为空,如果不是,就把它的next指向current的右子,这实现了子树内部的connect;

3.最后再看current的右子和current的next是否为空,如果不是,就把右子的next指向current->next的左子,实现子树间的connect。

逻辑有点绕,但是画图仔细分析是不难理解的。

代码如下:

 1 TreeLinkNode *current = root;
 2         TreeLinkNode *first_node_next_layer;
 3         while(current != NULL){
 4             first_node_next_layer = NULL;
 5             while(current != NULL){
 6                 TreeLinkNode *l = current->left;
 7                 TreeLinkNode *r = current->right;
 8 
 9                 if(first_node_next_layer == NULL && current->left != NULL)
10                     first_node_next_layer = current->left;
11 
12                 if(l != NULL)
13                     l->next = r;
14                 if(r != NULL && current->next != NULL)
15                     r->next = current->next->left;
16                 current = current->next;
17             }
18             current = first_node_next_layer;
19         }