From 0cc954e1f12276161cd2f9c504d81dfd29a721fd Mon Sep 17 00:00:00 2001 From: Ryo Oshima Date: Sat, 10 Jan 2026 18:03:39 +0900 Subject: [PATCH] 253. Meeting Rooms II --- 253/solution1_1.java | 55 +++++++++++++++++++++++++++++++++++++++ 253/solution2_1.java | 62 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 117 insertions(+) create mode 100644 253/solution1_1.java create mode 100644 253/solution2_1.java diff --git a/253/solution1_1.java b/253/solution1_1.java new file mode 100644 index 0000000..82d8054 --- /dev/null +++ b/253/solution1_1.java @@ -0,0 +1,55 @@ +/* +・概要 +自力解法 +5分くらいでAC + +・解き方。 +252 Meeting Roomと同様にまずintervalの開始でソートしてみていく。 +今回はかさなった重なったintervalがあったらそのぶん部屋を追加できるので、重なった部分を保持する必要がある。 +intervalを見るときは、その現在使われているintervalがないかをみて、現在のintervalの開始より前の時間で終了しているintervalは保持から削除していく。 +ということで、保持する必要があり、かつ保持したものを削除するのにソートされていた方が効率的なので両方を満たすPriorityQueueで実装する。 + +・計算量 +時間:O(nlogn) n:intervalsの要素数。 問題制約からnは10^4なので、だいたい10^5くらいなので、0.01sくらいで終わりそう +空間;O(n) + +・所感 +なんか実装方針がわかれば自然に実装ができるようになってきた気がする。 +言語化しづらいが、自分の頭でえがいたものパソコン(まあJavaだけど)に伝えるのができるようになってきた実感? +多分慣れと手段という知識が増えたこと、アルゴリズムを頭に描いてから実装という流れの定着、実装して理解より、理解して実装が増えてきたからな気がする +コードを頭の中でもんで再定義したり、他の人の解法で少し違う実装を見たりして、コードと思考がつながってきたのも大きい。 + + +*/ + +public class solution1_1 { + public int minMeetingRooms(int[][] intervals) { + List sortedIntervals = new ArrayList<>(); + for (int[] interval : intervals) { + sortedIntervals.add(new Interval(interval[0], interval[1])); + } + sortedIntervals.sort((a, b) -> (Integer.compare(a.start, b.start))); + PriorityQueue pq = + new PriorityQueue<>( + (a, b) -> (Integer.compare(a.end, b.end))); // pqよりusedRoomsとかのがコンテキストにあってそう。 + int maxRoomCounts = 0; + for (Interval interval : sortedIntervals) { + while (!pq.isEmpty() && pq.peek().end <= interval.start) { + pq.poll(); + } + pq.offer(interval); + maxRoomCounts = Math.max(maxRoomCounts, pq.size()); + } + return maxRoomCounts; + } + + class Interval { + int start; + int end; + + Interval(int start, int end) { + this.start = start; + this.end = end; + } + } +} diff --git a/253/solution2_1.java b/253/solution2_1.java new file mode 100644 index 0000000..71131ee --- /dev/null +++ b/253/solution2_1.java @@ -0,0 +1,62 @@ +/* +他の人の解法を参考にした。 +https://github.com/Satorien/LeetCode/pull/55/files +まずHeapにいれて、その後Heapの中身見ながらRoomを別の配列に入れていくもの。Roomを入れる配列は毎回ソートする。 +あーたしかにとはおもいつつも、毎回ソートするならpriorityqueueでもいいかもなと思った。 + +https://github.com/Kaichi-Irie/leetcode-python/pull/21/files +Roomいれる配列について維持したまま、置き換えていくイメージ。 + +https://github.com/Fuminiton/LeetCode/pull/49/files +タプルを使って開始と終了についてそれぞれ時刻とあわせた情報をもち、それを全部配列にいれてソートして±変えていくもの。 +これは思いつかない発想だったすごい。 + +https://github.com/Fuminiton/LeetCode/pull/49#discussion_r2221896539 +これはほんとに自分も癖つけた方がいいなと思った(計算量だけで満足することもおおいので) + + +ということで、開始・終了についてそれぞれ時刻とあわせた情報をもち、それを全部配列にいれてソートして±変えていくもので実装 +*/ + +public class solution2_1 { + public int minMeetingRooms(int[][] intervals) { + List sortedIntervals = new ArrayList<>(); + for (int[] interval : intervals) { + sortedIntervals.add(new MeetingEvent(interval[0], EventType.START)); + sortedIntervals.add(new MeetingEvent(interval[1], EventType.END)); + } + sortedIntervals.sort( + (a, b) -> { + if (a.time != b.time) { + return Integer.compare(a.time, b.time); + } + return a.type.compareTo(b.type); + }); + int needMaxRoomCounts = 0; + int needRoomCounts = 0; + for (MeetingEvent event : sortedIntervals) { + if (event.type == EventType.START) { + needRoomCounts++; + } else if (event.type == EventType.END) { + needRoomCounts--; + } + needMaxRoomCounts = Math.max(needMaxRoomCounts, needRoomCounts); + } + return needMaxRoomCounts; + } + + enum EventType { + END, + START + } + + class MeetingEvent { + int time; + EventType type; + + MeetingEvent(int time, EventType type) { + this.time = time; + this.type = type; + } + } +}