目次
完全な二分木が あると 、そのすべての葉ノードは同じレベルにあり、各親ノードには 2 つの子ノードがあります。バイナリ ツリーは次のように定義されます。
struct ノード { int val; ノード*左; ノード *右; ノード*次; }このポインタが次の右のノードを指すように、次のポインタのそれぞれに値を入力します。次の右のノードが見つからない場合、次のポインタは に設定されます
NULL
。最初は、すべての次のポインターが に設定されます
NULL
。例 1:
入力: root = [1,2,3,4,5,6,7] 出力: [1,#,2,3,#,4,5,6,7,#] 説明:指定されたバイナリ ツリーは次のとおりです。図 A に示すように、関数は、図 B に示すように、次のポインターをそれぞれ埋めて、次の右のノードを指すようにする必要があります。シリアル化された出力はレイヤー順のトラバーサルで配置され、同じレイヤー内のノードは次のポインターによって接続され、「#」は各レイヤーの終わりをマークします。例 2:
入力: root = [] 出力: []ヒント:
- ツリー内のノード数が
[0, 212 - 1]
範囲内にあります-1000 <= node.val <= 1000
高度な:
- 一定の追加スペースのみを使用できます。
- 再帰を使用して問題を解決することも要件を満たしますが、この問題で再帰プログラムが占有するスタック領域は、追加の領域の複雑さとしてカウントされません。
問題に対する反復的な解決策:
// 反復的な解決策: 注意して観察すると、2 つの接続方法があることがわかります。
// 1. 2 つの接続ポイントには共通の親ノードがあります
// 2. 2 つの接続点の親ノードは異なり、上位層の次の隣接ノードの 1 つのノードと左のノードです。
// 現在のノードに基づいて子ノードを処理できます。これは、レイヤーごとに処理することと同等です。
// したがって、ネストされたループが 2 つ必要になります。内側の水平ループはレイヤーを処理し、次のレイヤーを垂直に入力します。
コード:
/* // Definition for a Node. class Node { public int val; public Node left; public Node right; public Node next; public Node() {} public Node(int _val) { val = _val; } public Node(int _val, Node _left, Node _right, Node _next) { val = _val; left = _left; right = _right; next = _next; } }; */ class Solution { // 迭代解决:仔细观察发现有两种连接方式 // 1、两个连接点有共同父节点 // 2、两个连接点父节点不同,分别是一个节点和上一层邻居next的左节点 // 我们可以根据当前节点处理他的子节点,相当于一层一层处理 // 所以需要两个循环嵌套,里面的横向处理完该层,再竖向进入下一层 public Node connect(Node root) { // 特判:无节点则不需处理 if(root==null) return root; // 定义一个节点等于root Node pre=root; // 左节点不为空则这层需要处理,进入循环开始处理这一层 while(pre.left!=null){ Node tmp=pre; while(tmp!=null){ // 处理有共同父节点的连接点 tmp.left.next=tmp.right; // 处理父节点不同的连接点 if(tmp.next!=null){ tmp.right.next=tmp.next.left; } // 横向移动处理这一层未处理的节点 tmp=tmp.next; } // 竖向移动处理下一层 pre=pre.left; } return root; } }
操作結果: