【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         }
复制代码

 Java版本代码:

复制代码
 1 public class Solution {
 2     public void connect(TreeLinkNode root) {
 3         TreeLinkNode firstLayerNode = root;
 4         while(firstLayerNode != null){
 5             TreeLinkNode thislayerNode = firstLayerNode;
 6             firstLayerNode = firstLayerNode.left;           
 7             while(thislayerNode != null){
 8                 if(thislayerNode.left != null)
 9                     thislayerNode.left.next = thislayerNode.right;
10                 if(thislayerNode.right != null && thislayerNode.next != null)
11                     thislayerNode.right.next = thislayerNode.next.left;
12                 thislayerNode = thislayerNode.next;
13             }
14         }
15     }
16 }
复制代码

 

 

 

posted @   SunshineAtNoon  阅读(137)  评论(0编辑  收藏  举报
编辑推荐:
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示