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
161 changes: 161 additions & 0 deletions Binary_Tree_Zigzag_Level_Order_Traversal.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
### Step1

```python

from collections import deque

class Solution:
def zigzagLevelOrder(self, root: Optional[TreeNode]) -> List[List[int]]:
nodes_and_depthes = deque([(root, 0)])
zigzag_ordered = []
prev_depth = None
from_left = False
while nodes_and_depthes:
node, depth = nodes_and_depthes.popleft()
if not node:
continue
if prev_depth != depth:
if prev_depth and not from_left:
same_depth_nodes.reverse()
same_depth_nodes = []
from_left = not from_left
zigzag_ordered.append(same_depth_nodes)
Copy link

Choose a reason for hiding this comment

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

same_depth_nodeszigzag_ordered の末尾の要素の状態で、 same_depth_nodes に要素を追加していくという処理が直感的ではないように感じました。 same_depth_nodes に要素を追加したあとで、zigzag_ordered の末尾に追加したほうが、より分かりやすいコードになると思いました。

Copy link
Owner Author

Choose a reason for hiding this comment

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

ありがとうございます。
このほうが場合わけがいらず実装が簡潔になるのでこうしたのですが、確かに書いてる時にわかりにくいかもとなんとなく思ってました。

same_depth_nodes.append(node.val)
nodes_and_depthes.append((node.left, depth + 1))
nodes_and_depthes.append((node.right, depth + 1))
prev_depth = depth
if prev_depth and not from_left:
same_depth_nodes.reverse()
return zigzag_ordered
```

### Step2

https://discord.com/channels/1084280443945353267/1201211204547383386/1219179255615717399

- Zigzagじゃない方のStep2の最後で、current_levelとnext_levelを2つ持たず、要素数で管理するやつを自分も書いたが、確かに同じ変数で2種類のものを管理するのでややこしいかも
- 一般に、同じ変数に複数の役割を持たすのはあまり好ましくないかもと思った

https://github.com/fhiyo/leetcode/pull/29

- left_to_rightという変数名でも良い
- 突っ込む順番を逆にするより、フラグを立てて後からreverse()の方が遅くなるものの意図が明確で良い

https://github.com/TORUS0818/leetcode/pull/29

- next_levelを持つ実装
- 引き継ぎはcurrent_depth_nodesとfrom_leftで、current_depth_nodes_valとnext_depth_nodesの初期化は次の人に任せた
- 後で気づいたが、next_depth_nodesをwhileの外で持つ必要はない

```python
class Solution:
def zigzagLevelOrder(self, root: Optional[TreeNode]) -> List[List[int]]:
if not root:
return []
current_depth_nodes = [root]
from_left = True
next_depth_nodes = []
Copy link

Choose a reason for hiding this comment

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

消し忘れとかですかね

zigzag_ordered = []
while current_depth_nodes:
current_depth_nodes_val = []
next_depth_nodes = []
for node in current_depth_nodes:
current_depth_nodes_val.append(node.val)
if node.left:
next_depth_nodes.append(node.left)
if node.right:
next_depth_nodes.append(node.right)
if not from_left:
current_depth_nodes_val.reverse()
zigzag_ordered.append(current_depth_nodes_val)
from_left = not from_left
current_depth_nodes = next_depth_nodes
return zigzag_ordered
```

- DFSでの実装
- 反転を探索ついでにやるのはかなりややこしくなりそう(可読性も微妙になりそう)なのでやめといた

Choose a reason for hiding this comment

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

思ったほど酷いことにはならなそうです(これがいいかはおいておいて)

# Definition for a binary tree node.
# 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 not root:
            return []

        node_level_pairs = [(root, 0)]
        zigzag_ordered_lists = []
        while node_level_pairs:
            node, level = node_level_pairs.pop()
            while level >= len(zigzag_ordered_lists):
                zigzag_ordered_lists.append([])

            if level % 2:
                zigzag_ordered_lists[level].insert(0, node.val)
            else:
                zigzag_ordered_lists[level].append(node.val)

            if node.right: node_level_pairs.append((node.right, level + 1))
            if node.left: node_level_pairs.append((node.left, level + 1))
    
        return zigzag_ordered_lists

Copy link
Owner Author

Choose a reason for hiding this comment

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

なるほど、ありがとうございます。(返信遅くなりました)
同じ深さのnodeを突っ込み終わるタイミングがわからず、全部突っ込んでからreverse()ができないので、突っ込む時に左からか右からか決めるしかなさそうですね(そうするとdeque使った方が良さそうですね)


```python

class Solution:
def zigzagLevelOrder(self, root: Optional[TreeNode]) -> List[List[int]]:
if not root:
return []
zigzag_ordered = []
nodes_stack = [(root, 0)]
while nodes_stack:
node, depth = nodes_stack.pop()
while depth >= len(zigzag_ordered):
zigzag_ordered.append([])
zigzag_ordered[depth].append(node.val)
if node.right:
nodes_stack.append((node.right, depth + 1))
if node.left:
nodes_stack.append((node.left, depth + 1))
for i in range(len(zigzag_ordered)):

Choose a reason for hiding this comment

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

次のようにすると、i % 2の判定が不要になります。

        for i in range(1, len(zigzag_ordered), 2):

Copy link
Owner Author

Choose a reason for hiding this comment

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

なるほど、そういう選択肢はありませんでした、ありがとうございます

if i % 2:
zigzag_ordered[i].reverse()
return zigzag_ordered
```

## Step3

```python

class Solution:
def zigzagLevelOrder(self, root: Optional[TreeNode]) -> List[List[int]]:
if not root:
return []
result = []
current_depth_nodes = [root]
left_to_right = True
while current_depth_nodes:
next_depth_nodes = []
values_of_current_depth = []
for node in current_depth_nodes:
values_of_current_depth.append(node.val)
if node.left:
next_depth_nodes.append(node.left)
if node.right:
next_depth_nodes.append(node.right)
if not left_to_right:

Choose a reason for hiding this comment

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

好みの問題かもですが、Step2の最後のもののように、resultを構築してからreverse()する方が、left_to_rightが不要になるので読みやすくなるように思います。
resultを走査するコストはありますが、多くの場合は無視できる程度かなと

Copy link
Owner Author

Choose a reason for hiding this comment

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

確かにそうですね、結構パフォーマンスを意識していまいがちですが、実務だと可読性の方が大事だと思うので留意します

values_of_current_depth.reverse()
result.append(values_of_current_depth)
current_depth_nodes = next_depth_nodes
left_to_right = not left_to_right
return result
```

## Step4

- nodchipさんの指摘(same_depth_nodesに全部突っ込んだ後に、zigzag_orderedにsame_depth_nodesを入れた方がわかりやすい)などを反映

```python

from collections import deque

class Solution:
def zigzagLevelOrder(self, root: Optional[TreeNode]) -> List[List[int]]:
if not root:
return []
node_and_depth = deque([(root, 0)])
zigzag_ordered = []
same_depth_nodes = []
prev_depth = None
while node_and_depth:
node, depth = node_and_depth.popleft()
if prev_depth is not None and prev_depth != depth:
zigzag_ordered.append(same_depth_nodes)
same_depth_nodes = []
same_depth_nodes.append(node.val)
if node.left:
node_and_depth.append((node.left, depth + 1))
if node.right:
node_and_depth.append((node.right, depth + 1))
prev_depth = depth
zigzag_ordered.append(same_depth_nodes)
for i in range(1, len(zigzag_ordered), 2):
zigzag_ordered[i].reverse()
return zigzag_ordered
```