주차 요금 계산 - Lv.2
<문제>
https://school.programmers.co.kr/learn/courses/30/lessons/92341
<문제 풀이>
HashMap, TreeMap(정렬을 위해)를 사용하여 각 차량의 입차 시간과 총 주차 시간을 저장했다.
이 문제는 여러 가지 조건들을 통해 구현 능력을 확인하고, 자료구조를 적절히 활용하는 것에 초점은 둔 것 같다.
차량의 입차 시간을 저장하는 inTime Map과 차량의 총 주차 시간을 저장하는 parking Map을 선언했다.
차량 번호가 아닌 입/출차를 의미하는 "IN"/"OUT"을 중심으로 코드를 작성했다.
차량이 주차장에 들어오면(IN) inTime에 차량 번호와 입차 시간을 저장하고, 차량이 주차장을 나가면(OUT) 출차 시간에서 입차 시간을 뺀 만큼과 차량 번호는 parking에 저장한다.
parking에 저장된 총 주차 시간을 가지고 초과 요금을 계산해 최종적으로 반환되는 배열에 저장한다.
이 문제를 풀 때, 계속 런타임 에러가 걸렸던 부분이 있다.
"inTime.remove(entrySet.getKey());" 부분이다. 이 코드가 작성되어 있는 영역은 컬렉션이 순회하고 있는 영역이다.
즉, entrySet.getKey() 값이 사용되고 있는 상황에서 값을 삭제하면 동시성의 오류가 발생한다.
컬렉션 순회 중에는 iterator.remove()를 통해서만 값을 삭제할 수 있다.
해당 코드를 주석처리 해주면 런타임 에러가 발생하지 않는다.
<코드>
import java.util.Map;
import java.util.HashMap;
import java.util.TreeMap;
import java.util.Map.Entry;
public class parkingFee {
public static void main(String[] args) {
int[] fees = {180, 5000, 10, 600};
String[] records = {"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[] result = solution(fees, records);
for(int re : result) {
System.out.print(re + " ");
}
}
public static int[] solution(int[] fees, String[] records) {
//00:00 ~ 23:59
//입차 기록은 있지만 출차 기록이 없다면 23:59분에 출차한 것으로 간주함
//((주차 총 시간 - fees[0]) / fees[2]) * fees[3] + fees[1]
//HashMap<차량 번호, 입차 시간> inTime; String, String
//HashMap<차량 번호, 주차 시간> parking; String, Integer
int[] answer = {};
Map<String, Integer> parking = new TreeMap<>(); //차량의 총 주차 시간
Map<String, String> inTime = new HashMap<>(); //차량의 입차 시간
for(String record : records) {
String[] info = record.split(" ");
if(info[2].equals("IN")) { //입차
inTime.put(info[1], info[0]);
} else if(info[2].equals("OUT")){ //출차
int inTimeMin = calTime(inTime.get(info[1]));
int outTimeMin = calTime(info[0]);
int allTime = outTimeMin - inTimeMin;
if(parking.containsKey(info[1])) {
parking.put(info[1], parking.get(info[1]) + allTime);
} else {
parking.put(info[1], allTime);
}
inTime.remove(info[1]);
}
}
if(!inTime.isEmpty()) {
for(Entry<String, String> entrySet : inTime.entrySet()) {
int inTimeMin = calTime(entrySet.getValue());
int outTimeMin = calTime("23:59");
int allTime = outTimeMin - inTimeMin;
if(parking.containsKey(entrySet.getKey())) {
parking.put(entrySet.getKey(), parking.get(entrySet.getKey()) + allTime);
} else {
parking.put(entrySet.getKey(), allTime);
}
//inTime.remove(entrySet.getKey()); //-> 런타임오류 발생 이유
//keySet()을 이미 사용하고 있는 상황에서 키를 삭제해서 동시성의 오류가 발생한 것
}
}
answer = new int[parking.size()];
int idx = 0;
for(Entry<String, Integer> entrySet : parking.entrySet()) {
int time = entrySet.getValue();
if(time <= fees[0]) { //기본 시간만큼 주차한 경우
answer[idx] = fees[1];
} else { //초과 시간 계산
answer[idx] = fees[1] + (int) Math.ceil((time - fees[0]) / (double)fees[2]) * fees[3];
}
idx++;
}
return answer;
}
public static int calTime(String time) { //hh:MM -> MM
String[] timeArr = time.split(":");
return (Integer.parseInt(timeArr[0]) * 60) + Integer.parseInt(timeArr[1]);
}
}
'프로그래머스' 카테고리의 다른 글
[코딩테스트 연습] n ^ 2 배열 자르기 - Lv.2 (0) | 2023.10.11 |
---|---|
[코딩테스트 연습] 다음 큰 숫자 - Lv.2 (0) | 2023.09.26 |
[코딩테스트 연습] 명예의 전당(1) - Lv.1 (0) | 2023.08.03 |
[코딩테스트 연습] 다음에 올 숫자 - Lv.0 (0) | 2023.06.12 |
[코딩테스트 연습] 무작위로 K개의 수 뽑기 - Lv.0 (0) | 2023.06.05 |