안녕하세요. 오늘은 프로그래머스의 주차 요금 계산 문제를 풀어보겠습니다. 이 문제는 2022년도 KAKAO BLIND RECRUITMENT에서 출제되었습니다.
https://programmers.co.kr/learn/courses/30/lessons/92341
차량의 출차와 입차를 관리하는 HashMap(parkingLot)과 각 차량의 총 주차시간을 저장하는 HashMap(totalTimes)을 생성합니다.
key는 차량번호(Integer), value는 입차 시간(Date)입니다.
key는 차량번호(Integer), value는 총 주차시간(Integer)입니다.
차량의 입차와 출차를 확인하며 각 차량의 총 주차 시간을 구합니다. parkingLot hashMap에 주어진 차량번호가 저장되어 있다면 차량을 내보내야(출차) 하고, 저장되어 있지 않다면 차량을 들여보내야(입차) 합니다.
차량을 들여보낼 때는 별다른 로직이 필요 없습니다.
차를 내보낼 때는 차의 총 주차시간(totalTimes)을 업데이트 해야합니다. (출차 시간 - 입차 시간)을 totalTimes hashMap에 저장합니다. 만약 totalTimes hashMap에 이미 해당 차량이 주차한 시간이 저장되어 있다면, 이전 주차 시간에 새로운 주차 시간을 더해줍니다. 총 주차시간을 업데이트 한 후에는 parkingLot hashMap에서 차량번호를 remove합니다.
마지막까지(23:59까지) 안나간 차가 있으면 다 내보내야 합니다. 23:59분을 기준으로 출차 로직을 수행합니다.
총 주차 시간을 토대로 총 요금을 구합니다. 만약 어떤 차의 총 주차시간이 기본시간(fees[0])을 넘지 않으면, 그냥 기본요금(fees[1])만 내면 됩니다.
추가로, (총 주차시간 - 기본 주차시간)에서 단위 시간을 나눈 나머지가 0이 아니면, 단위 요금을 한번 더 더해줍니다.
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
class Solution {
private static Map<Integer, Date> parkingLot; //주차장 -> 입차, 출차 관리
private static Map<Integer, Integer> totalTimes; //시간 저장 map
public int[] solution(int[] fees, String[] records) throws ParseException {
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
parkingLot = new HashMap<>();
totalTimes = new HashMap<>();
for (String str : records) {
//05:34 5961 IN
String[] record = str.split(" ");
Date time = sdf.parse(record[0]);
int carNum = Integer.parseInt(record[1]);
if(parkingLot.containsKey(carNum)) {
findTotalTimes(carNum, time);
parkingLot.remove(carNum);
} else {
parkingLot.put(carNum, time);
}
}
//차 전부 다 내보내기
if(!parkingLot.isEmpty()) {
List<Integer> keySet = new ArrayList<>(parkingLot.keySet());
Date outTime = sdf.parse("23:59");
for (int key : keySet) {
findTotalTimes(key, outTime);
parkingLot.remove(key);
}
}
return findTotalCharges(fees);
}
//한 차량이 주차한 총 시간 구하기
private void findTotalTimes(int carNum, Date outTime) {
Date inTime = parkingLot.get(carNum);
long value = (outTime.getTime() - inTime.getTime())/60000;
if (totalTimes.containsKey(carNum)) {
value += totalTimes.get(carNum);
}
totalTimes.put(carNum, (int) value);
}
/*
fees[0] : 기본 시간(분) 180
fees[1] : 기본 요금(원) 5000
fees[2] : 단위 시간(분) 10
fees[3] : 단위 요금(원) 600
*/
//한 차량이 내야 하는 총 요금 구하기
private int[] findTotalCharges(int[] fees) {
List<Integer> keySet = new ArrayList<>(totalTimes.keySet());
Collections.sort(keySet);
int[] answer = new int[keySet.size()];
int basicTime = fees[0];
int basicFee = fees[1];
int unitTime = fees[2];
int unitFee = fees[3];
for (int i = 0; i < keySet.size(); i++) {
int key = keySet.get(i);
int timeValue = totalTimes.get(key);
if(timeValue <= basicTime) {
answer[i] = basicFee;
} else {
answer[i] = (timeValue - basicTime) / unitTime * unitFee + basicFee;
if ((timeValue - basicTime) % unitTime != 0) {
answer[i] += unitFee;
}
}
}
return answer;
}
}