From f52faf278a6418af2003e5fa15c4f9a29ccde8af Mon Sep 17 00:00:00 2001 From: Yota Maeda Date: Tue, 21 Jul 2026 22:57:13 +0900 Subject: [PATCH 1/2] step1,2 --- .../note.md | 41 +++++++++++++++ .../step1.py | 52 +++++++++++++++++++ .../step2.py | 52 +++++++++++++++++++ 3 files changed, 145 insertions(+) create mode 100644 103-Binary-Tree-Zigzag-Level-Order-Traversal/note.md create mode 100644 103-Binary-Tree-Zigzag-Level-Order-Traversal/step1.py create mode 100644 103-Binary-Tree-Zigzag-Level-Order-Traversal/step2.py diff --git a/103-Binary-Tree-Zigzag-Level-Order-Traversal/note.md b/103-Binary-Tree-Zigzag-Level-Order-Traversal/note.md new file mode 100644 index 0000000..21cecd5 --- /dev/null +++ b/103-Binary-Tree-Zigzag-Level-Order-Traversal/note.md @@ -0,0 +1,41 @@ +# 103. Binary Tree Zigzag Level Order Traversal + +https://leetcode.com/problems/binary-tree-zigzag-level-order-traversal/description/ + +## step1(まず通す) + +node を取り出す時に値をチェックすると反転の扱いが面倒そうと考えて、詰める時にチェックするようにした。 + +フラグを用意して切り替えることも考えたが、2階層セットで書けば同じことの繰り返しなのでコードの重複部分が増える代わりに考えることが減ると思って書いた。 + +## step2(整形&他の人のコードを読む) + +実際書いてみると、奇数階層と偶数階層で異なるのは右の子を先に見るか左の子を先に見るかだけなのでここをフラグ化して関数に切り出してみる。 + +フラグによる切り替え部分は以下のようにも書ける。ちょっとパズル的で読みづらいかもしれない。 + +```python + if left_first: + if node.left is not None: + next_level_values.append(node.left.val) + next_level_nodes.append(node.left) + + if node.right is not None: + next_level_values.append(node.right.val) + next_level_nodes.append(node.right) + + if not left_first: + if node.left is not None: + next_level_values.append(node.left.val) + next_level_nodes.append(node.left) +``` + +### 他の方のコード + +- https://github.com/naoto-iwase/leetcode/pull/31/changes#diff-18873955c02f8e2268cf8385696e9d0aa7cce7bd5e4d5059818cb2903515da83R15 + - 「levelごとのvaluesは、level内では常にleft to rightで一旦貯めていき、複数レベルのリストに格納する直前に反転するかどうか決めたらいい。」 + - この単純な事実に気づいていなかった。「node を取り出す時に値をチェックすると反転の扱いが面倒そう」と思い込んでいたが実際にはそうではなかった。 + - ただしリストのコピーは発生する。 + - とはいっても、Python で高速化してもしょうがない面はあるので読みやすさ的にこれがよさそう。 + +## step3(10分以内にさっとかける \* 3回) diff --git a/103-Binary-Tree-Zigzag-Level-Order-Traversal/step1.py b/103-Binary-Tree-Zigzag-Level-Order-Traversal/step1.py new file mode 100644 index 0000000..3d610b6 --- /dev/null +++ b/103-Binary-Tree-Zigzag-Level-Order-Traversal/step1.py @@ -0,0 +1,52 @@ +from typing import Optional + + +class TreeNode: + def __init__(self, val=0, left=None, right=None): + self.val = val + self.left = left + self.right = right + + +class Solution: + def zigzagLevelOrder(self, root: Optional[TreeNode]) -> list[list[int]]: + if root is None: + return [] + + values_by_level: list[list[int]] = [[root.val]] + nodes: list[TreeNode] = [root] + # 2階層ごとに同じことを繰り返すので、2階層セットでループを回す + while nodes: + # まず次のレベルを右から左へ見る + next_level_values: list[int] = [] + next_level_nodes: list[TreeNode] = [] + while nodes: + node = nodes.pop() + if node.right is not None: + next_level_values.append(node.right.val) + next_level_nodes.append(node.right) + if node.left is not None: + next_level_values.append(node.left.val) + next_level_nodes.append(node.left) + + if next_level_values: + values_by_level.append(next_level_values) + nodes = next_level_nodes + + # 次に、左から右へ + next_level_values = [] + next_level_nodes = [] + while nodes: + node = nodes.pop() + if node.left is not None: + next_level_values.append(node.left.val) + next_level_nodes.append(node.left) + if node.right is not None: + next_level_values.append(node.right.val) + next_level_nodes.append(node.right) + + if next_level_values: + values_by_level.append(next_level_values) + nodes = next_level_nodes + + return values_by_level diff --git a/103-Binary-Tree-Zigzag-Level-Order-Traversal/step2.py b/103-Binary-Tree-Zigzag-Level-Order-Traversal/step2.py new file mode 100644 index 0000000..380ef97 --- /dev/null +++ b/103-Binary-Tree-Zigzag-Level-Order-Traversal/step2.py @@ -0,0 +1,52 @@ +from typing import Optional + + +class TreeNode: + def __init__(self, val=0, left=None, right=None): + self.val = val + self.left = left + self.right = right + + +class Solution: + def traverse_next_level( + self, nodes: list[TreeNode], left_first: bool + ) -> tuple[list[int], list[TreeNode]]: + next_level_values: list[int] = [] + next_level_nodes: list[TreeNode] = [] + while nodes: + node = nodes.pop() + if left_first: + if node.left is not None: + next_level_values.append(node.left.val) + next_level_nodes.append(node.left) + if node.right is not None: + next_level_values.append(node.right.val) + next_level_nodes.append(node.right) + else: + if node.right is not None: + next_level_values.append(node.right.val) + next_level_nodes.append(node.right) + if node.left is not None: + next_level_values.append(node.left.val) + next_level_nodes.append(node.left) + + return next_level_values, next_level_nodes + + def zigzagLevelOrder(self, root: Optional[TreeNode]) -> list[list[int]]: + if root is None: + return [] + + values_by_level: list[list[int]] = [[root.val]] + nodes: list[TreeNode] = [root] + left_first = False # 根の直下は右から見る + while nodes: + next_level_values, next_level_nodes = self.traverse_next_level( + nodes, left_first + ) + if next_level_values: + values_by_level.append(next_level_values) + nodes = next_level_nodes + left_first = not left_first + + return values_by_level From 01f1568049dcfa245226639c834360ae045ddbd8 Mon Sep 17 00:00:00 2001 From: Yota Maeda Date: Tue, 21 Jul 2026 23:13:11 +0900 Subject: [PATCH 2/2] step3 --- .../note.md | 9 ++++- .../step3.py | 36 +++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 103-Binary-Tree-Zigzag-Level-Order-Traversal/step3.py diff --git a/103-Binary-Tree-Zigzag-Level-Order-Traversal/note.md b/103-Binary-Tree-Zigzag-Level-Order-Traversal/note.md index 21cecd5..c9aea51 100644 --- a/103-Binary-Tree-Zigzag-Level-Order-Traversal/note.md +++ b/103-Binary-Tree-Zigzag-Level-Order-Traversal/note.md @@ -36,6 +36,13 @@ node を取り出す時に値をチェックすると反転の扱いが面倒そ - 「levelごとのvaluesは、level内では常にleft to rightで一旦貯めていき、複数レベルのリストに格納する直前に反転するかどうか決めたらいい。」 - この単純な事実に気づいていなかった。「node を取り出す時に値をチェックすると反転の扱いが面倒そう」と思い込んでいたが実際にはそうではなかった。 - ただしリストのコピーは発生する。 - - とはいっても、Python で高速化してもしょうがない面はあるので読みやすさ的にこれがよさそう。 + - とはいっても、Python で高速化してもしょうがないし面はあるので、Python だけで書くなら読みやすさ的にこれがよさそう。 ## step3(10分以内にさっとかける \* 3回) + +zigzag じゃないバージョン(102: 前回の PR で解いた)とほぼ同じで、values を収集した後に二回に一回反転する実装。 + +[sorted は list を返す](https://docs.python.org/ja/3/library/functions.html#sorted)が、[reversed は要素を逆順に取り出すイテレータを返す](https://docs.python.org/ja/3/library/functions.html#reversed)ので sorted のノリで +`values_by_level.append(reversed(values))` と書くとエラーになる。 + +sequence.reverse() は in-place で逆順にして None を返すので `values_by_level.append(values.reverse())` も書けない。 diff --git a/103-Binary-Tree-Zigzag-Level-Order-Traversal/step3.py b/103-Binary-Tree-Zigzag-Level-Order-Traversal/step3.py new file mode 100644 index 0000000..2cc8260 --- /dev/null +++ b/103-Binary-Tree-Zigzag-Level-Order-Traversal/step3.py @@ -0,0 +1,36 @@ +from typing import Optional + + +class TreeNode: + def __init__(self, val=0, left=None, right=None): + self.val = val + self.left = left + self.right = right + + +class Solution: + def zigzagLevelOrder(self, root: Optional[TreeNode]) -> list[list[int]]: + if root is None: + return [] + + values_by_level = [] + nodes = [root] + is_left_to_right = True + while nodes: + values = [] + next_level = [] + for node in nodes: + values.append(node.val) + if node.left is not None: + next_level.append(node.left) + if node.right is not None: + next_level.append(node.right) + + if not is_left_to_right: + values.reverse() + values_by_level.append(values) + + nodes = next_level + is_left_to_right = not is_left_to_right + + return values_by_level