diff --git a/853. Car Fleet.md b/853. Car Fleet.md new file mode 100644 index 0000000..101b3a3 --- /dev/null +++ b/853. Car Fleet.md @@ -0,0 +1,144 @@ +## step1 とりあえず解く +- 計算量 + - 時間:O(NlogN) + - 空間:O(N) +- 反省点 + - やりたいことに対して必要以上に複雑になった気がする + - fleetの数さえあればいいから、Mapではなくintがあればよかった + - 直前のFleetのarrivalTimeだけあればいいからArrayDequeを使う必要はなかった + - 全体的に変数名がわかりにくい気がする + - 特に `entrySet` の命名がわかりにくい + + +```java +class Solution { + + private final record CarFleet(double arrivalTime, int count) {}; + + public int carFleet(int target, int[] position, int[] speed) { + Deque fleets = new ArrayDeque<>(); + Map carsPositionAndSpeed = createPositionDescendingOrderMap(position, speed); + + for (Map.Entry entrySet : carsPositionAndSpeed.entrySet()) { + int distance = target - entrySet.getKey(); + double arrivalTime = (double) distance / entrySet.getValue(); + if (!fleets.isEmpty() && fleets.peekLast().arrivalTime() >= arrivalTime) { + CarFleet lastFleet = fleets.pollLast(); + fleets.addLast(new CarFleet(lastFleet.arrivalTime(), lastFleet.count() + 1)); + } else { + fleets.addLast(new CarFleet(arrivalTime, 1)); + } + } + return fleets.size(); + } + + private Map createPositionDescendingOrderMap(int[] position, int[] speed) { + Map carsPositionAndSpeed = new TreeMap<>(Comparator.reverseOrder()); + for (int i = 0; i < position.length; i++) { + carsPositionAndSpeed.put(position[i], speed[i]); + } + return carsPositionAndSpeed; + } +} + +``` + +## step2 他の人の回答を見る +- 計算量 + - 時間:O(NlogN) + - 空間:O(N) +- やっていることは私が書いたStep1と同じ + - positonの降順で、positonとspeedを持つ配列を作成 + - stackに積んで、後ろの車が前の車に追いつくかどうかを確認 +- StackではなくArrayDequeを使うべきだと感じた + +```java +public class Solution { + public int carFleet(int target, int[] position, int[] speed) { + int[][] pair = new int[position.length][2]; + for (int i = 0; i < position.length; i++) { + pair[i][0] = position[i]; + pair[i][1] = speed[i]; + } + Arrays.sort(pair, (a, b) -> Integer.compare(b[0], a[0])); + Stack stack = new Stack<>(); + for (int[] p : pair) { + stack.push((double) (target - p[0]) / p[1]); + if (stack.size() >= 2 && + stack.peek() <= stack.get(stack.size() - 2)) + { + stack.pop(); + } + } + return stack.size(); + } +} +``` + +- 計算量 + - 時間:O(NlogN) + - 空間:O(N) +- Stackを使わない方法 +- こちらの方が登場する変数が少なくすみ、余計なデータ構造がないのでより良い回答に思える +- ただ、変数名はもう少しわかりやすい方が好ましいように感じる + - nやpairなど + - なんのpairなのかわかりにくいのと中身が何かわかりにくい +- 最終的にソートできればいいので、各要素をinsertした時点で順序が担保されるTreeMapを使わず配列を最後にソート + +```java +public class Solution { + public int carFleet(int target, int[] position, int[] speed) { + int n = position.length; + int[][] pair = new int[n][2]; + for (int i = 0; i < n; i++) { + pair[i][0] = position[i]; + pair[i][1] = speed[i]; + } + Arrays.sort(pair, (a, b) -> Integer.compare(b[0], a[0])); + + int fleets = 1; + double prevTime = (double)(target - pair[0][0]) / pair[0][1]; + for (int i = 1; i < n; i++) { + double currTime = (double)(target - pair[i][0]) / pair[i][1]; + if (currTime > prevTime) { + fleets++; + prevTime = currTime; + } + } + return fleets; + } +} +``` + +## step3 3回とく +- 計算量 + - 時間:O(NlogN) + - 空間:O(N) +- step2で見た他の人の回答を一部修正 + +```java +class Solution { + + private final record Car(int position, int speed) {}; + + public int carFleet(int target, int[] position, int[] speed) { + int carCount = position.length; + Car[] cars = new Car[carCount]; + for (int i = 0; i < carCount; i++) { + cars[i] = new Car(position[i], speed[i]); + } + Arrays.sort(cars, (a,b) -> Integer.compare(b.position(), a.position())); + int fleets = 1; + double previousArrivalTime = (double) (target - cars[0].position()) / cars[0].speed(); + for (int i = 1; i < carCount; i++) { + double arrivalTime = (double) (target - cars[i].position()) / cars[i].speed(); + if (previousArrivalTime < arrivalTime) { + fleets++; + previousArrivalTime = arrivalTime; + } + } + return fleets; + } +} + +``` \ No newline at end of file