From 495eed5c99d1d5a066c310f8cfd692367f2f5ca4 Mon Sep 17 00:00:00 2001 From: busker <165013324+hiroki-horiguchi-dev@users.noreply.github.com> Date: Sat, 13 Jun 2026 09:37:09 +0900 Subject: [PATCH 1/4] solve 98 --- tree-bst/98.md | 113 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 113 insertions(+) diff --git a/tree-bst/98.md b/tree-bst/98.md index e69de29..9f3d123 100644 --- a/tree-bst/98.md +++ b/tree-bst/98.md @@ -0,0 +1,113 @@ +- [98. Validate Binary Search Tree](https://leetcode.com/problems/validate-binary-search-tree/description/) +- 方針 + - Queue を用いる + - 初期値の `root.val` は `Long.MIN_VALUE ~ Long.MAX_VALUE` の間に収まっていればOK + - 同様に、左の子については、最大値が root.val になればよく、左の子の値判定は、`Long.MIN_VALUE ~ root.val` に収まっていればBSTとして適切 + - 同様に、右の子については、最小値が root.val になればよく、右の子の値判定は、`root.val ~ Long.MAX_VALUE` に収まっていればBSTとして適切 + - 上記を繰り返すだけではなく、一つ下のノードに落ちた時に左に落ちたのであれば、最大値を更新。右に落ちたのであれば最小値を更新して、許容される値の区間を更新し続ける必要がある + - 一般化すると、左に行く時は最大値を現在のノードの値で更新、右に行く時は現在のノードの値で最小値を更新すれば良い +- 実装時間: 20分 +```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 boolean isValidBST(TreeNode root) { + if (root == null) { + return false; + } + + Deque nodes = new ArrayDeque<>(); + nodes.addLast(new NodeWithRange(root, Long.MIN_VALUE, Long.MAX_VALUE)); + + while (!nodes.isEmpty()) { + NodeWithRange nodeWithRange = nodes.pollFirst(); + TreeNode node = nodeWithRange.node; + long min = nodeWithRange.min; + long max = nodeWithRange.max; + + if (node.val <= min || node.val >= max) { + return false; + } + + if (node.left != null) { + nodes.addLast(new NodeWithRange(node.left, min, node.val)); + } + + if (node.right != null) { + nodes.addLast(new NodeWithRange(node.right, node.val, max)); + } + } + + return true; + } + + private record NodeWithRange(TreeNode node, long min, long max){} +} +``` +- うまくいかず、40分程度格闘したコード +- 何がいけなかったのか? + - Queue に対するノードの追加と invalid の判定を同時に行おうとした点 +```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 boolean isValidBST(TreeNode root) { + if (root == null) { + return false; + } + + Deque nodes = new ArrayDeque<>(); + nodes.addLast(new NodeWithRange(root, Long.MIN_VALUE, Long.MAX_VALUE)); + while (!nodes.isEmpty()) { + NodeWithRange nodeWithRange = nodes.pollFirst(); + TreeNode node = nodeWithRange.node; + long min = nodeWithRange.min; + long max = nodeWithRange.max; + + if (node.left != null) { + if (node.left.val >= node.val || node.left.val <= min) { + return false; + } + nodes.addLast(new NodeWithRange(node.left, min, node.val)); + } + + if (node.right != null) { + if (node.right.val <= node.val || node.right.val >= max) { + return false; + } + nodes.addLast(new NodeWithRange(node.right, node.val, max)); + } + } + + return true; + } + + private record NodeWithRange(TreeNode node, long min, long max){} +} +``` \ No newline at end of file From 5b99978cbeda2703445baceeefef78e6732055b5 Mon Sep 17 00:00:00 2001 From: busker <165013324+hiroki-horiguchi-dev@users.noreply.github.com> Date: Sat, 13 Jun 2026 09:53:24 +0900 Subject: [PATCH 2/4] resolve 98 --- tree-bst/98.md | 63 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 62 insertions(+), 1 deletion(-) diff --git a/tree-bst/98.md b/tree-bst/98.md index 9f3d123..dc673a7 100644 --- a/tree-bst/98.md +++ b/tree-bst/98.md @@ -110,4 +110,65 @@ class Solution { private record NodeWithRange(TreeNode node, long min, long max){} } -``` \ No newline at end of file +``` + +- 時間を空けて解き直し、もっとシンプルにできる +```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 boolean isValidBST(TreeNode root) { + if (root == null) { + return false; + } + + Deque nodes = new ArrayDeque<>(); + nodes.addLast(new NodeWithRange(root, Long.MIN_VALUE, Long.MAX_VALUE)); + + while (!nodes.isEmpty()) { + NodeWithRange nodeWithRange = nodes.pollFirst(); + TreeNode node = nodeWithRange.node; + long min = nodeWithRange.min; + long max = nodeWithRange.max; + + if (node.val <= min) { + return false; + } + + if (node.val >= max) { + return false; + } + + if (node.left != null) { + // 最大値更新 + nodes.addLast(new NodeWithRange(node.left, min, node.val)); + } + + if (node.right != null) { + // 最小値更新 + nodes.addLast(new NodeWithRange(node.right, node.val, max)); + } + } + + return true; + } + + private record NodeWithRange(TreeNode node, long min, long max){} +} +``` + +- 前回の課題をまとめる + - \ No newline at end of file From 2371201f388b038cf598db19d2aba9177700b6f2 Mon Sep 17 00:00:00 2001 From: busker <165013324+hiroki-horiguchi-dev@users.noreply.github.com> Date: Mon, 15 Jun 2026 21:46:37 +0900 Subject: [PATCH 3/4] =?UTF-8?q?Iterable,=20Collction,=20List,=20Set,=20Que?= =?UTF-8?q?ue=20=E3=81=AE=E9=96=A2=E4=BF=82=E6=80=A7=E3=81=AB=E3=81=A4?= =?UTF-8?q?=E3=81=84=E3=81=A6=E3=81=BE=E3=81=A8=E3=82=81=E3=82=8B=E9=80=94?= =?UTF-8?q?=E4=B8=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tree-bst/98.md | 166 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 160 insertions(+), 6 deletions(-) diff --git a/tree-bst/98.md b/tree-bst/98.md index dc673a7..6aa00d8 100644 --- a/tree-bst/98.md +++ b/tree-bst/98.md @@ -144,11 +144,7 @@ class Solution { long min = nodeWithRange.min; long max = nodeWithRange.max; - if (node.val <= min) { - return false; - } - - if (node.val >= max) { + if (node.val <= min || node.val >= max) { return false; } @@ -171,4 +167,162 @@ class Solution { ``` - 前回の課題をまとめる - - \ No newline at end of file + - [103. Binary Tree Zigzag Level Order Traversal #27 line 145](https://github.com/hiroki-horiguchi-dev/leetcode/pull/27/changes)で自分に出した課題 + + ```terminaloutput + Iterable + └── Collection + ├── List + │ ├── ArrayList + │ └── LinkedList + ├── Set + │ ├── HashSet + │ └── TreeSet + └── Queue + ├── LinkedList (List も実装してる) + └── ArrayDeque + ``` + + - [Iterable](https://github.com/openjdk/jdk/blob/a13dd293a811a6ba829696e68cd2150de2cb2f17/src/java.base/share/classes/java/lang/Iterable.java) + - Iterable は、Javaの Collection 自体が実装しているので、Collectionを継承ないし実装しているクラス(List, Queue, Set, Map) は全て for を使うことができる + ```java + public interface Iterable { + Iterator iterator(); + + default void forEach(Consumer action) { + Objects.requireNonNull(action); + for (T t : this) { + action.accept(t); + } + } + default Spliterator spliterator() { + return Spliterators.spliteratorUnknownSize(iterator(), 0); + } + } + ``` + - [Collections](https://github.com/openjdk/jdk/blob/a13dd293a811a6ba829696e68cd2150de2cb2f17/src/java.base/share/classes/java/util/Collection.java) + ```java + package java.util; + + import java.util.function.IntFunction; + import java.util.function.Predicate; + import java.util.stream.Stream; + import java.util.stream.StreamSupport; + + public interface Collection extends Iterable { + + int size(); + + boolean isEmpty(); + + boolean contains(Object o); + + Iterator iterator(); + + Object[] toArray(); + + T[] toArray(T[] a); + + default T[] toArray(IntFunction generator) { + return toArray(generator.apply(0)); + } + + boolean add(E e); + + boolean remove(Object o); + + boolean containsAll(Collection c); + + boolean addAll(Collection c); + + boolean removeAll(Collection c); + + default boolean removeIf(Predicate filter) { + Objects.requireNonNull(filter); + boolean removed = false; + final Iterator each = iterator(); + while (each.hasNext()) { + if (filter.test(each.next())) { + each.remove(); + removed = true; + } + } + return removed; + } + + boolean retainAll(Collection c); + + void clear(); + + boolean equals(Object o); + + int hashCode(); + + @Override + default Spliterator spliterator() { + return Spliterators.spliterator(this, 0); + } + + default Stream stream() { + return StreamSupport.stream(spliterator(), false); + } + + default Stream parallelStream() { + return StreamSupport.stream(spliterator(), true); + } + } + ``` + - 抽象メソッド(実装必須) + - 情報取得: `size(), isEmpty(), contains()` + - 走査: `iterator()` + - 変換: `toArray(), toArray(T[])` + - 追加/削除: `add(), remove(), addAll(), removeAll(), retainAll(), clear()` + - 存在確認: `containsAll()` + - 比較: `equals(), hashCode()` + - 実装しているクラスのまとめ + ```terminaloutput + Collection [interface] + ├── SequencedCollection [interface] (Java 21〜) + │ ├── List [interface] + │ │ ├── ArrayList + │ │ ├── LinkedList (※Dequeも実装) + │ │ ├── Vector + │ │ │ └── Stack + │ │ └── CopyOnWriteArrayList + │ ├── SequencedSet [interface] (Java 21〜 / Setを継承) + │ │ ├── LinkedHashSet (※HashSetの子クラス) + │ │ └── TreeSet (※NavigableSet経由で継承) + │ └── Deque [interface] (※Queueも継承) + │ ├── ArrayDeque + │ ├── LinkedList (※Listも実装) + │ ├── ConcurrentLinkedDeque + │ └── BlockingDeque [interface] + │ └── LinkedBlockingDeque + │ + ├── Set [interface] + │ ├── HashSet + │ │ └── LinkedHashSet (※SequencedSetも実装) + │ ├── EnumSet + │ ├── TreeSet (※NavigableSet経由) + │ └── CopyOnWriteArraySet + │ + ├── Queue [interface] + │ ├── PriorityQueue + │ ├── ConcurrentLinkedQueue + │ ├── Deque [interface] (※上記SequencedCollectionの枠内へ移動) + │ └── BlockingQueue [interface] + │ ├── ArrayBlockingQueue + │ ├── LinkedBlockingQueue + │ ├── PriorityBlockingQueue + │ ├── SynchronousQueue + │ └── LinkedTransferQueue + │ + └── AbstractCollection [abstract] + ├── AbstractList [abstract] ──> ArrayList, Vector などの親 + │ └── AbstractSequentialList [abstract] ──> LinkedList の親 + ├── AbstractSet [abstract] ──> HashSet, TreeSet などの親 + └── AbstractQueue [abstract] ──> PriorityQueue などの親 + ``` + - Map は実装していないので注意。Map を entrySet で回せているように見えるのは Set が Iterator を実装しているからで Map が Iterator を実装しているからではない + - + \ No newline at end of file From d52444d904717cf5cf32d4694e162e985368ba67 Mon Sep 17 00:00:00 2001 From: busker <165013324+hiroki-horiguchi-dev@users.noreply.github.com> Date: Sat, 4 Jul 2026 15:04:49 +0900 Subject: [PATCH 4/4] Update 98.md --- tree-bst/98.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tree-bst/98.md b/tree-bst/98.md index 6aa00d8..21ee068 100644 --- a/tree-bst/98.md +++ b/tree-bst/98.md @@ -185,6 +185,7 @@ class Solution { - [Iterable](https://github.com/openjdk/jdk/blob/a13dd293a811a6ba829696e68cd2150de2cb2f17/src/java.base/share/classes/java/lang/Iterable.java) - Iterable は、Javaの Collection 自体が実装しているので、Collectionを継承ないし実装しているクラス(List, Queue, Set, Map) は全て for を使うことができる + - CSZAP の チューリング完全あたりで出てきた内容っぽいので入門コンピュータ科学12章をつまみ読んだ ```java public interface Iterable { Iterator iterator(); @@ -324,5 +325,6 @@ class Solution { └── AbstractQueue [abstract] ──> PriorityQueue などの親 ``` - Map は実装していないので注意。Map を entrySet で回せているように見えるのは Set が Iterator を実装しているからで Map が Iterator を実装しているからではない - - + - 面倒くさくなってきたので一旦ここで push する + - あとは気が向けば戻ってきて続きをやる \ No newline at end of file