본문 바로가기
PS

[자바] 프로그래머스 - 주차 요금 계산 (2022 카카오 블라인드) / HashMap 풀이

by 제이._ 2022. 11. 10.

https://school.programmers.co.kr/learn/courses/30/lessons/92341

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

Level2, 정답률 57% 난이도의 2022년도 카카오 블라인드 채용 문제입니다.

 


 

문제 간단 설명

문제를 간단하게 요약하자면 다음과 같습니다.

 

매개변수로 들어오는 String[] records와 int[] fees를 이용해서 주차요금을 구하는 문제인데,

records 배열의 각각의 요소는 다음과 같습니다. "03:00 1234 IN" 이처럼 "시간 차량번호 입/출차" 형식입니다.

 

우리는 이 records와, 주차 요금인 fees 가지고 정답을 구하면 됩니다.

 

 

문제 접근 방법 및 풀이

카카오 문제는 테스트를 돌릴 때 생각 외의 경우에서 틀리는 경우가 많기 때문에, 저는 이 문제를 보고 예외의 경우를 먼저 떠올렸습니다.

예외의 경우는 다음과 같습니다.

 

 

생각하면서 풀어야 할 예외의 경우

1. records안에서 차량의 입차는 여러 번이 될 수 있다. (누적 주차 시간)

2. IN은 찍혔지만, OUT은 찍히지 않은 경우 23:59를 나간 시간으로 간주한다. (OUT이 안 찍힐 수도 있음)

 

 

문제를 다음과 같이 나눠서 풀었습니다.

1. 누적 주차 시간을 구한다.

  1-1. 예외 1번 (차량의 입차는 여러 번이 될 수 있다.) 생각하기

  1-2. 예외 2번 (OUT이 찍히지 않은 경우) 생각하기

 

2. 누적 주차 시간을 기준으로 주차 요금을 구한다.

  

3. 차량 넘버를 오름차순으로 정렬 후 주차 요금을 리턴해준다.

 

 

 

이렇게 문제 해결을 정리하고 순서대로 구현을 했습니다.

위에서 나눠 푸는 경우를 보면서 "Key : Value 형식으로 관리하기 좋은 HashMap을 이용해야겠다." 라는 생각을 했습니다.

 

 

HashMap은 3개를 만들었습니다.

1. 차량번호 : 입차 시간

2. 차량번호 : 누적 주차 시간

3. 차량번호 : 주차 요금

 

 

위에 문제를 해결하기 위해서 접근은 다음과 같이 했습니다.

1. records 배열을 하나씩 for문으로 탐색하면서, IN인 경우 1번 HashMap을 채워주고 / OUT인 경우 1번 HashMap에서 차량넘버를 지워주고, 2번 HashMap의 누적 주차 시간을 더해주기  (이렇게 해야 여러 번 입차가 되는 예외 1번을 해결해줄 수 있고, 예외 2번인 OUT이 찍히지 않은 경우를 관리 할 수 있기 때문)

 

2. 예외 2번을 해결해주기 위해서, 1번 HashMap에 지워지지 않은 키 값이 있다면, 23:59를 출차 시간으로 간주하고, 누적 주차 시간을 구해서 2번 HashMap을 채워주기

 

3. 3번 HashMap을 위해서 주차 요금을 계산한 후 채워주기

 

4. 정렬하고 리턴

 

 

정답 코드

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class Solution {
    public static List<Integer> solution(int[] fees, String[] records) {
        HashMap<String, String> numberAndInTime = new HashMap<>(); // 차랑번호, In시간
        HashMap<String, Integer> timeOfParking = new HashMap<>(); // 누적 주차시간 (차량번호, 시간(분))
        HashMap<String, Integer> priceOfParking = new HashMap<>(); // 주차 비용 (차량번호, 비용)

        for (String record : records) {
            String[] recordArr = record.split(" ");
            if (recordArr[2].equals("IN")) {
                numberAndInTime.put(recordArr[1], recordArr[0]);
            } else if (recordArr[2].equals("OUT")) {
                String inTime = numberAndInTime.get(recordArr[1]);
                String outTime = recordArr[0];
                // 누적 주차시간 더함
                timeOfParking.put(recordArr[1],
                        timeOfParking.getOrDefault(recordArr[1], 0) + getRecordParkingTime(inTime, outTime));
                numberAndInTime.remove(recordArr[1]);
            }
        }

        // 출차를 안한 차량 계산
        for (String record : records) {
            String[] recordArr = record.split(" ");
            if (numberAndInTime.containsKey(recordArr[1])) {
                String inTime = numberAndInTime.get(recordArr[1]);
                timeOfParking.put(recordArr[1],
                        timeOfParking.getOrDefault(recordArr[1], 0) + getRecordParkingTime(inTime, "23:59"));
                numberAndInTime.remove(recordArr[1]);
            }
        }

        // 주차 요금 계산
        for (String key : timeOfParking.keySet()) {
            int parkingTime = timeOfParking.get(key); // 주차 시간
            priceOfParking.put(key, getPriceOfParking(parkingTime, fees));
        }


        // 정렬 후 값 리턴
        return priceOfParking.entrySet().stream()
                .sorted(Map.Entry.comparingByKey())
                .map(Map.Entry::getValue)
                .collect(Collectors.toList());
    }

    // in, out 시간으로 주차 시간을 구해주는 함수
    public static int getRecordParkingTime(String inTime, String outTime) {
        String[] outTimes = outTime.split(":");
        String[] inTimes = inTime.split(":");

        int outMin = Integer.parseInt(outTimes[0]) * 60 + Integer.parseInt(outTimes[1]);
        int inMin = Integer.parseInt(inTimes[0]) * 60 + Integer.parseInt(inTimes[1]);

        return (outMin - inMin);

    }

    // 주차 가격을 측정
    public static int getPriceOfParking(int parkingTime, int[] fees) {
        int price = 0;
        if (parkingTime <= fees[0]) {
            return fees[1];
        } else {
            parkingTime -= fees[0];
            price += fees[1];
            price += (Math.ceil(parkingTime / (fees[2] * 1.0)) * fees[3]);
        }
        return price;
    }
 }