【leetcode】117. 填充每个节点的下一个右侧节点指针 II( Populating Next Right Pointers in Each Node II)


题目描述

【leetcode】117. 填充每个节点的下一个右侧节点指针 II( Populating Next Right Pointers in Each Node II)

给定一个二叉树

struct Node {
  int val;
  Node *left;
  Node *right;
  Node *next;
}

填充它的每个 next 指针,让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点,则将 next 指针设置为 NULL。

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

进阶:

  • 你只能使用常量级额外空间。
  • 使用递归解题也符合要求,本题中递归程序占用的栈空间不算做额外的空间复杂度。

示例:

输入:root = [1,2,3,4,5,null,7]
输出:[1,#,2,3,#,4,5,7,#]
解释:给定二叉树如图 A 所示,你的函数应该填充它的每个 next 指针,以指向其下一个右侧节点,如图 B 所示。

提示:

  • 树中的节点数小于 6000
  • -100 <= node.val <= 100

第一次解答

思路
这一题显然使用层次遍历求解会更简单,但是通常我们在进行层次遍历时,每遍历一层就需要用队列去存储下一层的结点,用作下一轮遍历,显然不符合进阶要求你只能使用常量级额外空间。那么我们如何在常数额外空间下进行层次遍历呢?
本题比较特别,每个结点提供了next成员,从每一次最左边结点沿着next就可以遍历完该层。
但next默认为空,我们怎么得到设置好了的next呢?可以采用自顶向下的方法。对于根节点,我们很容易将其下一层结点连接好,连接好后,就可以对下一层结点进行遍历,然后对连接下下层结点…以此类推。
这里有个细节就是,下一层的开始结点,是下一层最左边的那个结点。具体见代码。

test case:
[-1,-7,9,null,null,-1,-7,null,8,-9]
[1,2,3,4,5,null,7]
[1,2,3,4,5,null,6,7,null,null,null,null,8]

代码:

/*
// 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(nullptr == root)
            return root;

        Node* pRoot = root;
        while(nullptr != pRoot){
    
    
        	// 拿到这一层的起始结点
            Node* pNode = pRoot;
            Node* pPre = nullptr;
            // 通过next遍历这一层
            // 将这一层的孩子的next都连接起来
            while(nullptr != pNode){
    
    
               if(nullptr != pNode->left){
    
    
                    if(nullptr != pPre)
                        pPre->next = pNode->left;
                    pPre = pNode->left;
                }
                if(nullptr != pNode->right){
    
    
                    if(nullptr != pPre)
                        pPre->next = pNode->right;
                    pPre = pNode->right;
                }
                pNode = pNode->next;
                
               }
            // 计算下一层起始结点pRoot
            // 下一个pRoot应该是下一层最靠左的结点
            while(nullptr != pRoot && nullptr == pRoot->left && 
                    nullptr == pRoot->right){
    
    
                pRoot = pRoot->next;
            }
            if(nullptr != pRoot)
                pRoot = pRoot->left == nullptr ? pRoot->right : pRoot->left;
        }

        return root;
    }
};

结果:

截图

第二次解答

思路
看了官方题解,找下一层起始结点的工作,可以放在连接孩子的过程中。

代码:

/*
// 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(nullptr == root)
            return root;

        Node* pRoot = root;
        while(nullptr != pRoot){
    
    
        	// 拿到这一层的起始结点
            Node* pNode = pRoot;
            Node* pPre = nullptr;
            pRoot = nullptr;// 置空,由下面找孩子时得到下一层最靠左的结点
            // 通过next遍历这一层
            // 将这一层的孩子的next都连接起来
            while(nullptr != pNode){
    
    
               if(nullptr != pNode->left){
    
    
                    if(nullptr != pPre)
                        pPre->next = pNode->left;
                    else
                        pRoot = pNode->left;
                    pPre = pNode->left;
                }
                if(nullptr != pNode->right){
    
    
                    if(nullptr != pPre)
                        pPre->next = pNode->right;
                    else
                        pRoot = pNode->right;
                    pPre = pNode->right;
                }
                pNode = pNode->next;
                
               }
            // 下一个pRoot应该是下一层最靠左的结点
            // while(nullptr != pRoot && nullptr == pRoot->left && 
            //         nullptr == pRoot->right){
    
    
            //     pRoot = pRoot->next;
            // }
            // if(nullptr != pRoot)
            //     pRoot = pRoot->left == nullptr ? pRoot->right : pRoot->left;
        }

        return root;
    }
};

结果:

在这里插入图片描述

相关/参考链接

猜你喜欢

转载自blog.csdn.net/a435262767/article/details/105169575
今日推荐