Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
177 changes: 177 additions & 0 deletions 102. Binary Tree Level Order Traversal.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
# step 1
階層別BFSをすれば良い

ノードの数をnとして、
- time complexity: O(n)
- space complexity: O(n)
```python
class Solution:
def levelOrder(self, root: Optional[TreeNode]) -> List[List[int]]:
if root is None:
return []

nodes = [root]
result = []
while nodes:
values_in_this_level = []
nodes_in_next_level = []
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

好みの問題ですが変数名の中に前置詞が入ると変数名が長くなりがちなので、それを避けるためにnext_level_nodesみたいにすることもあります

for node in nodes:
values_in_this_level.append(node.val)
if node.left is not None:
nodes_in_next_level.append(node.left)
if node.right is not None:
Comment on lines +20 to +22

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is not None はなくてもシンプルで良いですが、書いた方が明示的という人もいるかもしれません。
好みでしょうか。

nodes_in_next_level.append(node.right)
result.append(values_in_this_level)
nodes = nodes_in_next_level
return result
```

Noneもとりあえずつっこんであとから処理するタイプの階層別BFS。
```python
class Solution:
def levelOrder(self, root: Optional[TreeNode]) -> List[List[int]]:
nodes = [root]
result = []
while True:
nodes = list(filter(None, nodes))

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

取り出す前にfilterで除去するというのは、今まで考えたことがありませんでしたが、振る舞いとしては理にかなった操作だと感じました。

if not nodes:
break
values_in_this_level = []
nodes_in_next_level = []
for node in nodes:
values_in_this_level.append(node.val)
nodes_in_next_level.append(node.left)
nodes_in_next_level.append(node.right)
result.append(values_in_this_level)
nodes = nodes_in_next_level
return result
```

# step 2
- https://github.com/Mike0121/LeetCode/pull/7/files#r1587410964
- >resultはもう少し命名頑張っても良いかも。level_ordered_valuesとかどうでしょうか?
- https://github.com/hayashi-ay/leetcode/pull/32/files
- DFS preorder recursive traversal、階層別でないdequeを使ったBFS

感想:BFS以外の書き方が思いつかなかったが、levelさえトラックしていればDFSでやろうが動作する。
Copy link

@olsen-blue olsen-blue Mar 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DFSは直感に反する感じがして食わず嫌いしてましたが、解けるんですね。勉強になりました。

それと、深さごとに、入る部屋[]が決まってて、そこに放り込んでいく操作ですが、辞書みたいな使い方で良いですね。
level_ordered_values[level].append(node.val)


iterative, preorder DFS traversal
- time complexity: O(n)
- space complexity: O(n)
```python
class Solution:
def levelOrder(self, root: Optional[TreeNode]) -> List[List[int]]:
level_ordered_values = []
nodes_and_levels = [(root, 0)]
while nodes_and_levels:
node, level = nodes_and_levels.pop()
if node is None:
continue
while not len(level_ordered_values) > level:
level_ordered_values.append([])
level_ordered_values[level].append(node.val)
nodes_and_levels.append((node.right, level + 1))
nodes_and_levels.append((node.left, level + 1))
return level_ordered_values
```

recursive, preorder DFS traversal,
2パターン書いてみたが、あまり名前がしっくりこない。
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

全体的に私は不満ないです。大規模言語モデルがいい案くれたりします。


- time complexity: O(n)
- space complexity: O(n)
```python
class Solution:
def levelOrder(self, root: Optional[TreeNode]) -> List[List[int]]:
def traverse_nodes_in_preorder(
node: Optional[TreeNode],
level: int
) -> None:
if node is None:
return

nonlocal level_ordered_values
while not len(level_ordered_values) > level:
Copy link

@colorbox colorbox Mar 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

条件部分にnotがあると読む時に反転させる一手間で若干読みづらくなるので、notをつけると読みやすくなる状況以外はnotをつけないことをおすすめします。

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

確かに上から下に読むものと考えたらここの否定は分かりにくいですね。

自分の中では、このループを抜けたつぎの行のlevel_ordered_values[level].append(node.val)で例外を発生させない条件の否定みたいな意味で書いてました。
つまり、ループを抜ければ、level_ordered_values[level].append(node.val)はうまく通るだろうみたいなニュアンスです。

Copy link

@colorbox colorbox Mar 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ここwhileである必然性がなさそうで、なぜwhileなんだろうという違和感を感じます。

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://discord.com/channels/1084280443945353267/1200089668901937312/1211248049884499988
これを参考にしてます。
preorder traversalをしており一段飛ばしになるとかはないので、ifでもいい場所ではあります。
必然性とまで言えるような論拠はないです。

level_ordered_values.append([])
level_ordered_values[level].append(node.val)
traverse_nodes_in_preorder(node.left, level + 1)
traverse_nodes_in_preorder(node.right, level + 1)

level_ordered_values = []
traverse_nodes_in_preorder(root, 0)
return level_ordered_values
```

```python
class Solution:
def levelOrder(self, root: Optional[TreeNode]) -> List[List[int]]:
def collect_values_in_preorder(
level_ordered_values: List[List[int]],
node: Optional[TreeNode],
level: int
) -> List[List[int]]:
if node is None:
return level_ordered_values
while not len(level_ordered_values) > level:
level_ordered_values.append([])
level_ordered_values[level].append(node.val)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

この書き方「階層化していないBFS」でも使っていますが、便利ですね。

collect_values_in_preorder(
level_ordered_values,
node.left,
level + 1
)
collect_values_in_preorder(
level_ordered_values,
node.right,
level + 1
)
return level_ordered_values
return collect_values_in_preorder([], root, 0)
```

階層化していないBFS
```python
from collections import deque


class Solution:
def levelOrder(self, root: Optional[TreeNode]) -> List[List[int]]:
level_ordered_values = []
nodes_and_levels = deque([(root, 0)])
while nodes_and_levels:
node, level = nodes_and_levels.popleft()
if node is None:
continue
while not len(level_ordered_values) > level:
level_ordered_values.append([])
level_ordered_values[level].append(node.val)
nodes_and_levels.append((node.left, level + 1))
nodes_and_levels.append((node.right, level + 1))
return level_ordered_values
```

# step 3

結局最初の書き方に戻った

```python
class Solution:
def levelOrder(self, root: Optional[TreeNode]) -> List[List[int]]:
if root is None:
return []

level_ordered_values = []
nodes_in_level = [root]
while nodes_in_level:
nodes_in_next_level = []
values_in_level = []
for node in nodes_in_level:
values_in_level.append(node.val)
if node.left is not None:
nodes_in_next_level.append(node.left)
if node.right is not None:
nodes_in_next_level.append(node.right)
nodes_in_level = nodes_in_next_level
level_ordered_values.append(values_in_level)
return level_ordered_values
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

好みなのですが、変数名が全体的に長く感じました。

```