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
145 changes: 145 additions & 0 deletions tree-bst/103.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
- [103. Binary Tree Zigzag Level Order Traversal](https://leetcode.com/problems/binary-tree-zigzag-level-order-traversal/description/)
- 条件
- The number of nodes in the tree is in the range [0, 2000].
- -100 <= Node.val <= 100
- 方針
- Queue
- [前回といた問題(102. Binary Tree Level Order Traversal)](https://github.com/hiroki-horiguchi-dev/leetcode/pull/26)と同様にQueueを用いる
- root を Queue に詰めながら、for でまわす方針は前回と同じだが、
- zigzag にしないといけないので、2つの方針がある
1. leftToRight を用意し、for のなかで Queue から取り出した TreeNode を `List<Integer>[→ → →] , List<Integer>[← ← ←]`に詰めるを繰り返す方針
2. for のなかで取り出した TreeNode を一旦 `List<Integer>[→ → →]` に詰めるけど、rightToLeft だけ、Collections.reverse() で反転させる
- コストの点で考えると、前者の方が逆順にするための計算量を食わないので良いと考える
- 時間計算量: ver1. `O(N)`, ver2. ~~`O(N^2)` Collections.reverse() に O(N) かかるため、[Collections.reverse() Method in Java with Examples
](https://www.geeksforgeeks.org/java/collections-reverse-method-in-java-with-examples/)~~ 内側で回る回数の総和がNであって、毎回N回回るわけじゃないので `O(N)`とカウントして良い
- 空間計算量: ver1. `O(N)`, ver2. `O(N)`
- 実装時間
- ver1. 20分
- ver2. 2分

## Queue ver.1 LinkedListを使う

```java
import java.util.LinkedList;

/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public List<List<Integer>> zigzagLevelOrder(TreeNode root) {
List<List<Integer>> result = new ArrayList<>();

if (root == null) {
return result;
}

Deque<TreeNode> nodes = new ArrayDeque<>();
boolean isLeftToRight = true;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

識別子が動詞の原形や命令形から始まっている場合、関数名のように感じる場合があります。自分なら leftToRight と名付けると思います。

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

コメントありがとうございます。
あれ、本当ですか・・・
is~ を、「その状態かどうか?」を示すフラグ用の変数名として、今まで参画したプロダクトの本番コードでも多々使ってきてしまいました。

nodes.addLast(root);

while (!nodes.isEmpty()) {
// 本当は List<Integer> で受けたいが、jdk21未満だと List に addLast, addFirst がないため、コンパイルエラーになる可能性があるので、LinkedList で受けている。

@nodchip nodchip Jun 8, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

LinkedList は、 add 毎に新しいオブジェクトが作られ、遅いイメージがあります。実際には速度を計ってみないと何とも言えません。

Deque<Integer> temp = new ArrayDeque<>() を使う手もあります。
https://docs.oracle.com/javase/jp/8/docs/api/java/util/ArrayDeque.html

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

コメントありがとうございます。

キューとして使われるときはLinkedListよりも高速です。

おっしゃる通りだと思いました。

// LinkedList は List を継承しているので、result に add する分には問題ない
LinkedList<Integer> temp = new LinkedList<>();
int size = nodes.size();

for (int i = 0; i < size; i++) {
TreeNode node = nodes.pollFirst();
if (isLeftToRight) {
temp.addLast(node.val);
} else {
temp.addFirst(node.val);
}

if (node.left != null) {
nodes.addLast(node.left);
}

if (node.right != null) {
nodes.addLast(node.right);
}
}

isLeftToRight = !isLeftToRight;
result.add(temp);
}

return result;
}
}

```

## Queue ver.2 Collections.reverse() を使う
```java
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public List<List<Integer>> zigzagLevelOrder(TreeNode root) {
List<List<Integer>> result = new ArrayList<>();

if (root == null) {
return result;
}

Deque<TreeNode> nodes = new ArrayDeque<>();
boolean isLeftToRight = true;
nodes.addLast(root);

while (!nodes.isEmpty()) {
List<Integer> temp = new ArrayList<>();
int size = nodes.size();

for (int i = 0; i < size; i++) {
TreeNode node = nodes.pollFirst();
temp.add(node.val);

if (node.left != null) {
nodes.addLast(node.left);
}

if (node.right != null) {
nodes.addLast(node.right);
}
}

if (!isLeftToRight) {
Collections.reverse(temp);
}
isLeftToRight = !isLeftToRight;
result.add(temp);
}

return result;
}
}

```

## 次の問題に取り組む前の課題
- Iterable, List, Queue, Dequeue, LinkedList の継承関係を把握する