您的位置:首页 > 其它

LeetCode 117:填充每个节点的下一个右侧节点指针 II

2020-07-18 05:20 232 查看

目录

LeetCode 117:填充每个节点的下一个右侧节点指针 II

题目描述

给定一个完美二叉树,其所有叶子节点都在同一层,每个父节点都有两个子节点。二叉树定义如下:

struct Node {
int val;
Node *left;
Node *right;
Node *next;
}
填充它的每个 next 指针,让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点,则将 next 指针设置为 NULL。

初始状态下,所有 next 指针都被设置为 NULL。

【示例】

解题

    对比LeetCode 116:填充每个节点的下一个右侧节点指针,二叉树不再是完美二叉树,但整体思路都是借助已经建立的同一层的连接关系,需要额外考虑当前节点右边的那个节点可能在更遥远的地方,而不是其父节点下一节点的右子节点。对于当前节点:

  1. 如果存在右子节点,则右子节点与其右边第一个出现的节点连接。
  2. 如果存在左子节点,则左子节点与其右边第一个出现的节点连接。

    如何找到“右边第一个出现的节点”的位置呢?只要沿着其父节点一直向右寻找,直到找到第一个出现的子节点为止。这个过程也可以反过来,用递归的方式,即我们可以先找到最右边的节点,然后返回这个节点位置,直到找到其左边第一个节点,此时它是这个“左边第一个节点”的“右边第一个节点”。然后建立这两个节点的连接,这时候,当前位置的节点依然是它“左边第一个节点”的“右边第一个节点”。以此递归下去直到当前层完全建立连接。
    当二叉树不再是完美二叉树时,会带来另外一个问题,那就是下一层的起点问题。下一层的起点应该是下一层出现的第一个节点位置。只需要将层间递归返回的最后一个节点位置作为起点即可。
以下是代码:

递归

/*
// Definition for a Node.
class Node {
public:
int val;
Node* left;
Node* right;
Node* next;

Node() : val(0), left(NULL), right(NULL), next(NULL) {}

Node(int _val) : val(_val), left(NULL), right(NULL), next(NULL) {}

Node(int _val, Node* _left, Node* _right, Node* _next)
: val(_val), left(_left), right(_right), next(_next) {}
};
*/

class Solution {
public:
//用于层间递归的函数
Node *slice_connect(Node *node){
if (node==NULL)
return NULL;
//next记录最右边第一个节点
Node *next = slice_connect(node->next);
//如果存在右子节点,则右子节点与其右边第一个出现的节点连接,并把右子节点作为右边第一个节点
if (node->right){
node->right->next = next;
next = node->right;
}
//如果存在左子节点,则左子节点与其右边第一个出现的节点连接,并把左子节点作为右边第一个节点
if (node->left){
node->left->next = next;
next = node->left;
}
return next;
}
Node* connect(Node* root) {
if (root==NULL)
return NULL;

Node *cur_node = root;
while(cur_node){
cur_node = slice_connect(cur_node);  //将层间递归返回的最后一个节点位置作为下一层起点
}

return root;
}
};

迭代

    与递归方法相比,在同一层建立关系时只能从左到右,因此无法得到其右边第一个节点,但反过来,我们可以记录左边第一个节点。在层间遍历过程中:

  1. 如果当前节点存在左子节点,则下一层左边第一个节点(如果不为空的话)与其左子节点建立连接,并用其左子节点更新左边第一个节点。
  2. 如果当前节点存在右子节点,则下一层左边第一个节点(如果不为空的话)与其右子节点建立连接,并用其右子节点更新左边第一个节点。

    还有一个需要注意的地方是,下一层起始位置。由于层间遍历时由左到右,所以需要额外引入变量来记录下一层起始位置。
    以下是代码:

/*
// Definition for a Node.
class Node {
public:
int val;
Node* left;
Node* right;
Node* next;

Node() : val(0), left(NULL), right(NULL), next(NULL) {}

Node(int _val) : val(_val), left(NULL), right(NULL), next(NULL) {}

Node(int _val, Node* _left, Node* _right, Node* _next)
: val(_val), left(_left), right(_right), next(_next) {}
};
*/

class Solution {
public:
Node* connect(Node* root) {
if (root==NULL)
return NULL;

Node *cur_node = root, *first_child = root->left ? root->left : root->right; //记录下一层第一个子节点位置
//外层由上到下
while (first_child){
Node *pre_node = NULL, *next_child = NULL;
//内层由左到右
while (cur_node){
if (cur_node->left){
if (pre_node)
pre_node->next = cur_node->left;
pre_node = cur_node->left;
//记录下下层第一个子节点位置,用于更新下一层第一个子节点位置
if (next_child == NULL)
next_child = pre_node->left ? pre_node->left : pre_node->right;
}
if (cur_node->right){
if (pre_node)
pre_node->next = cur_node->right;
pre_node = cur_node->right;
if (next_child == NULL)
next_child = pre_node->left ? pre_node->left : pre_node->right;
}
cur_node = cur_node->next;
}
cur_node = first_child;
first_child = next_child;
}
return root;
}
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐