Populating -next-right-pointers-in-each-node-ii populating-next-right-pointers-in-each-node-ii
タイトル説明
「各ノードに次の右ポインタを配置する」について引き続き考えてください。この質問で
は、指定されたツリーが任意のバイナリツリーである場合はどうなりますか?以前のアルゴリズムは引き続き有効ですか?
注:
使用できる追加のメモリスペースは
、次のようになります。
次のように与えられたバイナリツリーは次のとおりです。
1↵/↵23↵/↵4 5 7後は
あなたが与える関数を呼び出し、木になる必要があります:
1 - >NULL↵/↵2 - > 3 - >NULL↵/↵4 -> 5-> 7-> NULL
問題「各ノードに次の右ポインタを配置する」のフォローアップ。
与えられたツリーが任意の二分木である可能性がある場合はどうなりますか?以前のソリューションは引き続き機能しますか?
注意:
一定の余分なスペースのみを使用できます。
たとえば
、次の二分木があるとすると、
1↵ / ↵ 2 3↵ / ↵ 4 5 7↵
関数を呼び出すと、ツリーは次のようになります。
1 -> NULL↵ / ↵ 2 -> 3 -> NULL↵ / ↵ 4-> 5 -> 7 -> NULL
問題解決のアイデア
アイデア1:レベルトラバーサル
各レイヤーをトラバースするときは、cur配列を使用してレイヤーのすべてのノードを保存し、各レイヤーをトラバースした後、cur配列を再度トラバースして、レイヤーの各ノードを右の兄弟にリンクします。
右の兄弟は必ずしも厳密に隣接している必要はなく、複数のノードを分離できます。つまり、ノードBが同じレイヤーのノードAの右側にある限り、ノードBはの右兄弟であると言われます。ノードA
最後のノードにはライト兄弟がいないため、レイヤーの最後のノードに到達するかどうかを区別するように注意してください
/**
* Definition for binary tree with next pointer.
* struct TreeLinkNode {
* int val;
* TreeLinkNode *left, *right, *next;
* TreeLinkNode(int x) : val(x), left(NULL), right(NULL), next(NULL) {}
* };
*/
class Solution {
public:
void connect(TreeLinkNode *root) {
if(root == NULL) return ;
queue<TreeLinkNode *> myque;
myque.push(root); //根节点入队
while(!myque.empty()) {
vector<TreeLinkNode*> cur; //保存每一层所有的节点
int size = myque.size(); //记录每一层的节点数
//对每一层的节点进行操作
for(int i = 0; i < size; i ++) {
TreeLinkNode* p = myque.front();
myque.pop();
cur.push_back(p);
if(p -> left) myque.push(p -> left);
if(p -> right) myque.push(p -> right);
}
//将该层的每一个节点链接到右兄弟中
int cur_size = cur.size();
for(int i = 0; i < cur_size - 1; i ++) {
cur[i] -> next = cur[i + 1];
}
}
}
};
改善:レイヤーの各ノードで操作する場合、cur配列にストレージを追加することなく、キュー内の右の兄弟に直接リンクされます。
/**
* Definition for binary tree with next pointer.
* struct TreeLinkNode {
* int val;
* TreeLinkNode *left, *right, *next;
* TreeLinkNode(int x) : val(x), left(NULL), right(NULL), next(NULL) {}
* };
*/
class Solution {
public:
void connect(TreeLinkNode *root) {
if(root == NULL) return ;
queue<TreeLinkNode *> myque;
myque.push(root); //根节点入队
while(!myque.empty()) {
vector<TreeLinkNode*> cur; //保存每一层所有的节点
int size = myque.size(); //记录每一层的节点数
//对每一层的节点进行操作
for(int i = 0; i < size; i ++) {
TreeLinkNode* p = myque.front();
myque.pop();
cur.push_back(p);
if(p -> left) myque.push(p -> left);
if(p -> right) myque.push(p -> right);
if(i < size - 1) {
//如果没有到达该层最后一个节点,则链接右兄弟
p -> next = myque.front();
}
}
}
}
};
アイデア2:リンクリスト
- 現在の層のすべてのノードの次のポインタが設定されている場合、これに従って、次の層のすべてのノードの次のポインタも順番に設定できます。
- アイデア:各レイヤーをリンクリストと見なし、curを使用して現在のレイヤーをトラバースします。トラバース中、curが指すノードのすべての子ノード(つまり、次のレイヤー)はすべて、が指すリンクリストに文字列化されます。 pによって。
head.next
次のレイヤーの最初のノードを保持することにより、仮想ヘッドノードヘッドを作成します。使用できるのはポインターのみであることに注意してください。head->next
/**
* Definition for binary tree with next pointer.
* struct TreeLinkNode {
* int val;
* TreeLinkNode *left, *right, *next;
* TreeLinkNode(int x) : val(x), left(NULL), right(NULL), next(NULL) {}
* };
*/
class Solution {
public:
void connect(TreeLinkNode *root) {
while(root) {
TreeLinkNode head(-1), *p; //创建一个虚拟头结点
p = &head;
for(auto cur = root; cur; cur = cur -> next) {
//将当前层的所有孩子节点串到下一层的链表中
if(cur -> left) {
p -> next = cur -> left;
p = p -> next;
}
if(cur -> right) {
p -> next = cur -> right;
p = p -> next;
}
}
root = head.next;
}
}
};