タイトル説明
[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;
}
};
結果: