木の走査

01 / 一文で言うと

木の走査アルゴリズムはどれも各ノードをちょうど 1 回ずつ訪れる —— 違うのは、子への再帰的下降のうちで「訪問」がいつ起こるか、その一点だけ。
問題指定の順序で二分木を走査する二分木[1, 2, 3, 4, 5, ·, 6]順序前順
123456
出力—— まだ何もない ——
深さ優先 —— 前順はノードを子への再帰の前に訪れる。
ステップ
0 / 7
訪問中
訪問済み
0 / 6
順序
前順
0 / 7

02 / パターンの骨格

# 深さ優先 —— 3 つの変種は「訪問」の位置だけが違うtraverse(node):if node is null: returnvisit(node) // 前順traverse(node.left)visit(node) // 中順traverse(node.right)visit(node) // 後順# 幅優先 —— 反復、キューを使うlevel_order(root):q [root]while q not empty:node q.dequeue(); visit(node)enqueue node.left, node.right

03 / このパターンを使うべき合図

「BST の中順」
二分探索木のソート済み出力は中順から生まれる —— これは BST の性質であって、中順一般の性質ではない。
「階層ごと」
木を行ごとに処理する必要があるとき —— ノードの深さ、ジグザグ出力、 「右側のビュー」など。キューによる階層順が道具。
「ボトムアップ / 子が先」
子の答えがわからないと親の答えを決められない場合 —— 部分木の和、高さ、経路など。後順なら子が先に訪れることが保証される。
「シリアライズ / 複製」
木の文字列表現を作る、あるいはノードごとに複製する。多くは明示的な null マーカー付きの前順 —— これで構造を曖昧さなく表せる。

04 / よくある落とし穴

後順が必要なときに中順を使う。
子の答えから親の答えを計算するもの —— 部分木の和、高さ、直径 —— は 必ず親より前に子を訪れる必要がある。それが後順。 中順では一部の子が訪れるのが遅すぎる。
null チェックを忘れる。
再帰走査の最初の行が if node is null: return。 これを抜くと、葉ノードの存在しない子ごとに null を参照してしまう。 アニメーションではこれを明示している —— 空の部分木はそもそも描かれない。
呼び出しスタックを出力の順序と混同する。
再帰の自然な呼び出しスタックは訪問の順序ではない。 1 つのノードは前順訪問の前から後順訪問の後までスタックに乗っている —— 同じノードの 3 つの異なる「瞬間」。

05 / LeetCode で練習

中級42

01Validate Binary Search Tree— LC 9802Recover Binary Search Tree— LC 9903Binary Tree Level Order Traversal— LC 10204Binary Tree Zigzag Level Order Traversal— LC 10305Construct Binary Tree from Preorder and Inorder Traversal— LC 10506Construct Binary Tree from Inorder and Postorder Traversal— LC 10607Binary Tree Level Order Traversal II— LC 10708Path Sum II— LC 11309Sum Root to Leaf Numbers— LC 12910Binary Search Tree Iterator— LC 17311Binary Tree Right Side View— LC 19912Kth Smallest Element in a BST— LC 23013Lowest Common Ancestor of a Binary Search Tree— LC 23514Lowest Common Ancestor of a Binary Tree— LC 23615Binary Tree Vertical Order Traversal— LC 31416House Robber III— LC 33717N-ary Tree Level Order Traversal— LC 42918Path Sum III— LC 43719Serialize and Deserialize BST— LC 44920Delete Node in a BST— LC 45021Convert BST to Greater Tree— LC 53822Maximum Width of Binary Tree— LC 66223Insert into a Binary Search Tree— LC 70124Smallest Subtree with all the Deepest Nodes— LC 86525Construct Binary Tree from Preorder and Postorder Traversal— LC 88926Distribute Coins in Binary Tree— LC 97927Smallest String Starting From Leaf— LC 98828Construct Binary Search Tree from Preorder Traversal— LC 100829Binary Search Tree to Greater Sum Tree— LC 103830Lowest Common Ancestor of Deepest Leaves— LC 112331Tree Diameter— LC 124532Smallest Common Region— LC 125733Deepest Leaves Sum— LC 130234Maximum Product of Splitted Binary Tree— LC 133935Longest ZigZag Path in a Binary Tree— LC 137236Balance a Binary Search Tree— LC 138237Count Good Nodes in Binary Tree— LC 144838Diameter of N-Ary Tree— LC 152239Lowest Common Ancestor of a Binary Tree II— LC 164440Lowest Common Ancestor of a Binary Tree III— LC 165041Create Binary Tree From Descriptions— LC 219642Most Profitable Path in a Tree— LC 2467