[Leetcode] 117.各ノードIIの次の右ポインターの設定(各ノードIIの次の右ポインターの設定)


タイトル説明

[Leetcode] 117.各ノードIIの次の右ポインターの設定(各ノードIIの次の右ポインターの設定)

二分木を考える

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

このポインターが次の右ノードを指すように、次の各ポインターを入力します。次の正しいノードが見つからない場合、次のポインタはNULLに設定されます。

初期状態では、次のポインタはすべてNULLに設定されています。

上級:

  • 一定の余分なスペースしか使用できません。
  • 再帰を使用して問題を解決することも要件を満たします。この問題で再帰プログラムによって占有されるスタックスペースは、追加のスペースの複雑さとしてカウントされません。

例:

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

促す:

  • ツリーのノード数が6000未満です
  • -100 <= node.val <= 100

最初の答え


この質問の考え方は、階層的トラバーサルを使用すると明らかに簡単に解決できますが、通常、階層的トラバーサルを実行する場合、1つのレイヤーをトラバースするたびにキューを使用して次のレイヤーのノードを格納する必要があります。これは、明らかに次のトラバースのラウンドには適していません。注文の要件你只能使用常量级额外空间では、一定の余分なスペースで階層をトラバースするにはどうすればよいでしょうか。
この質問は非常に特殊であり、各ノードは次のメンバーを提供し、レイヤーは左にあるノードから次のメンバーに移動することができます。
しかし、nextはデフォルトでは空です。次のセットを取得するにはどうすればよいですか?トップダウン方式を使用できます。ルートノードの場合は、次のレイヤーのノードを簡単に接続できます。接続が完了したら、次のレイヤーのノードをトラバースしてから、下のレイヤーのノードを接続できます。
ここでの詳細の1つは、次のレイヤーの開始ノードが次のレイヤーの左端のノードであることです。詳細については、コードを参照してください。

テストケース:
[-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