[Java] 프로그래머스(level-2) - 주차 요금 계산
문제 풀이
이 문제는 HashMap을 활용하여 문자열을 정수형으로 변환해가며 시간 계산하면 되는 문제이다.
아이디어 도출
주차장에 입차된 차는 출차가 되는 것을 입출차라고 본다면 입차만 있는 차의 경우 23:59
분에 출차하는 것으로 간주해야 한다. 입차만 있는 차들을 23:59
분에 출차시키는 방법을 알아보자.
- 차마다 입차시간과 출차시간을 HashMap(A)과 차별 총 주차시간을 담을 HashMap(B)까지 총 2개의 HashMap을 사용한다.
- 주어진 입충차내역 배열을 순회하며 입차일 경우 A 맵에 key로 차번호, value로 입차시간을 저장한다.
- 출차일 경우 A 맵에서 입차내역을 가져온 후 출차내역과 입차내역을 비교하여 주차시간을 계산한 후 B 맵에 차번호를 key로, 주차시간을 value로 저장한다.
위 3가지 과정을 모두 마쳤다면, 입차내역만 있는 차들은 A 맵에 남아있을 것이다. 이 차들은 입차내역만 있고 출차내역이 없어 23:59
분에 출차시켜야 할 차들이라고 생각하면 된다. 그래서 A맵을 한번 더 순회하며 23:59
분에 출차내역과 입차내역을 비교하여 주차시간을 계산하고 B 맵에 저장한다!
그러면 모든 차들의 입차내역과 출차내역을 바탕으로 계산된 총 주차시간이 담긴 B 맵을 가지고 주차요금을 계산하면 된다. 이때, Map을 순회하면서 remove() 메서드 사용시 런타임 에러를 유의해야 한다.
런타임 에러?!
마지막에 자정에 OUT하는 차들의 주차시간을 계산할 때 런타임에러가 발생할 수 있다. Map에 남아있는 차들은 23:59에 나가는 차들이기 때문에 한번 더 Map을 순회하며 주차시간을 연산하게 되는데, 앞서 IN 시간을 담은 Map에서 처럼 Map의 원소를 삭제하게 되면 런타임 에러가 발생한다.
런타임 에러가 발생하는 이유는 Map의 keySet() 메서드로 순회하고 있는 도중 key를 삭제하려고 할 경우 동시성 오류가 발생하기 때문이다.
문제 풀이를 위해 작성한 코드는 아래와 같다.
작성 코드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
import java.util.*;
class Solution {
public int[] solution(int[] fees, String[] records) {
HashMap<String, String> tempMap = new HashMap<>();
TreeMap<String, Integer> timeMap = new TreeMap<>();
ArrayList<Integer> result = new ArrayList<>();
for(String record : records) {
String[] split = record.split(" ");
String time = split[0];
String carNumber = split[1];
if(record.contains("IN")) {
tempMap.put(carNumber, time);
} else if(record.contains("OUT")) {
int min = getMin(time, tempMap.get(carNumber));
timeMap.put(carNumber, timeMap.getOrDefault(carNumber, 0)+min);
tempMap.remove(carNumber);
}
}
if(!tempMap.isEmpty()) {
for(String carNumber : tempMap.keySet()) {
int min = getMin("23:59", tempMap.get(carNumber));
timeMap.put(carNumber, timeMap.getOrDefault(carNumber, 0)+min);
// 여기서 남은 tempMap의 원소를 remove하면 런타임 에러가 발생한다.
// 런타임 에러가 발생하는 이유는 Map의 keySet() 메서드로 순회하고 있는 도중 key를 삭제하려고 할 경우 동시성 오류가 발생하기 때문이다.
// tempMap.remove(carNumber);
}
}
for(String carNumber : timeMap.keySet()) {
if(timeMap.get(carNumber) <= fees[0]) {
result.add(fees[1]);
continue;
}
int price = (int) (fees[1] + Math.ceil((double)(timeMap.get(carNumber) - fees[0]) / fees[2]) * fees[3]);
result.add(price);
}
return result.stream().mapToInt(Integer::intValue).toArray();
}
static int getMin(String out, String in) {
String[] out_time = out.split(":");
String[] in_time = in.split(":");
return (Integer.parseInt(out_time[0]) - Integer.parseInt(in_time[0])) * 60 + (Integer.parseInt(out_time[1]) - Integer.parseInt(in_time[1]));
}
public static void main(String[] args) {
Solution sol = new Solution();
// int[] fees = new int[]{180, 5000, 10, 600};
// String[] records = new String[]{"05:34 5961 IN",
// "06:00 0000 IN",
// "06:34 0000 OUT",
// "07:59 5961 OUT",
// "07:59 0148 IN",
// "18:59 0000 IN",
// "19:09 0148 OUT",
// "22:59 5961 IN",
// "23:00 5961 OUT"};
// int[] fees = new int[]{120, 0, 60, 591};
// String[] records = new String[]{"16:00 3961 IN",
// "16:00 0202 IN",
// "18:00 3961 OUT",
// "18:00 0202 OUT",
// "23:58 3961 IN"};
int[] fees = new int[]{1, 461, 1, 10};
String[] records = new String[]{"00:00 1234 IN"};
sol.solution(fees, records);
}
}
회고
출처
- —
- 해당 문제의 저작권은 문제를 만든이에게 있으며 자세한 내용은 문제 링크에서 참조바랍니다.