본문 바로가기
자료구조 & 알고리즘/문제 풀이 (프로그래머스)

주차 요금 계산

by 정구정구 2026. 6. 15.

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

 

프로그래머스

SW개발자를 위한 평가, 교육의 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프

programmers.co.kr

처음 작성한 코드 (정답 코드)

import java.util.*;

class Solution {
    public int[] solution(int[] fees, String[] records) {
                HashMap<String, String> inMap = new HashMap<>();
        HashMap<String, Integer> totalTimeMap = new HashMap<>();

        for (String record : records) {

            String[] splitRecord = record.split(" ");
            String time = splitRecord[0];
            String carNumber = splitRecord[1];
            String contents = splitRecord[2];

            if (contents.equals("IN")) {
                inMap.put(carNumber,time);
            }
            else {
                totalTimeMap.merge(carNumber, timeCal(inMap.get(carNumber), time), Integer::sum);
                inMap.remove(carNumber);
            }
        }

        // 출차가 없는 애들 계산
        for (Map.Entry<String, String> entry : inMap.entrySet()) {
            totalTimeMap.merge(entry.getKey(), timeCal(entry.getValue(), "23:59"), Integer::sum);
        }

        List<Integer> answer = new ArrayList<>();
        List<String> keySet = new ArrayList<>(totalTimeMap.keySet());
        Collections.sort(keySet);

        for (String key : keySet) {
            answer.add(computeFee(fees, totalTimeMap.get(key)));
        }

        // 결과 리턴
        return answer.stream().mapToInt(i->i).toArray();
    }

    public static int timeCal(String inTime, String outTime) {

        String[] splitInTime = inTime.split(":");
        String[] splitOutTime = outTime.split(":");

        return (Integer.parseInt(splitOutTime[0])*60 + Integer.parseInt(splitOutTime[1]))
                - (Integer.parseInt(splitInTime[0])*60 + Integer.parseInt(splitInTime[1]));

    }

    public static int computeFee(int[] fees, int time) {

        // 요금 정리
        int basicTime = fees[0];
        int basicFee = fees[1];
        int unitTime = fees[2];
        int unitFee =  fees[3];

        int totalFee = basicFee;

        // 계산
        time -= basicTime;
        if (time <= 0) return totalFee;

        double doubleTime = time;
        totalFee += (int) (Math.ceil(doubleTime/unitTime) * unitFee);

        return totalFee;
    }
}

 

 

수정했으면 좋았을 부분

  • HashMap -> TreeMap
HashMap<String, Integer> totalTimeMap = new HashMap<>();

 

HashMap이 아니라 TreeMap을 썼다면 자동으로 오름차순으로 정렬되기 때문에 

 Collections.sort(keySet);

위와 같은 정렬 코드를 쓸 필요가 없어진다.

 

  • 더 좋은 알고리즘
        HashMap<String, String> inMap = new HashMap<>();
        HashMap<String, Integer> totalTimeMap = new HashMap<>();

        for (String record : records) {

            String[] splitRecord = record.split(" ");
            String time = splitRecord[0];
            String carNumber = splitRecord[1];
            String contents = splitRecord[2];

            if (contents.equals("IN")) {
                inMap.put(carNumber,time);
            }
            else {
                totalTimeMap.merge(carNumber, timeCal(inMap.get(carNumber), time), Integer::sum);
                inMap.remove(carNumber);
            }
        }

        // 출차가 없는 애들 계산
        for (Map.Entry<String, String> entry : inMap.entrySet()) {
            totalTimeMap.merge(entry.getKey(), timeCal(entry.getValue(), "23:59"), Integer::sum);
        }

 작성한 코드에서 입차를 Map에 집어넣고, 출차 시 Map에서 꺼내서 시간을 계산해서 totalTimeMap에 집어넣는다. 그리고 입차 기록만 있는 차들을 다시 한 번 순회하면서 계산하여 totalTimeMap에 집어넣는다.

 하지만 입차할 때 [입차 ~ "23:59"]시간을 totalTimeMap에 넣어두고, 출차 시 totalTimeMap에 넣어둔 값에서 [출사 ~ "23:59"] 시간을 빼주는 방법으로 코드를 짠다면 inMap을 구현할 필요도 없고 전체 순회를 한 번 줄일 수 있다.

 

 

수정한 코드

import java.util.*;

class Solution {
    public int[] solution(int[] fees, String[] records) {
        TreeMap<String, Integer> totalTimeMap = new TreeMap<>();

        for (String record : records) {

            String[] splitRecord = record.split(" ");
            String time = splitRecord[0];
            String carNumber = splitRecord[1];
            String contents = splitRecord[2];

            int minute = timeCal(time, "23:59");

            if (contents.equals("OUT")) {
                minute *= -1;
            }
            totalTimeMap.merge(carNumber, minute, Integer::sum);
        }

        List<Integer> answer = new ArrayList<>();
        List<String> keySet = new ArrayList<>(totalTimeMap.keySet());

        for (String key : keySet) {
            answer.add(computeFee(fees, totalTimeMap.get(key)));
        }

        // 결과 리턴
        return answer.stream().mapToInt(i->i).toArray();
    }

    public static int timeCal(String inTime, String outTime) {

        String[] splitInTime = inTime.split(":");
        String[] splitOutTime = outTime.split(":");

        return (Integer.parseInt(splitOutTime[0])*60 + Integer.parseInt(splitOutTime[1]))
                - (Integer.parseInt(splitInTime[0])*60 + Integer.parseInt(splitInTime[1]));

    }

    public static int computeFee(int[] fees, int time) {

        // 요금 정리
        int basicTime = fees[0];
        int basicFee = fees[1];
        int unitTime = fees[2];
        int unitFee =  fees[3];

        int totalFee = basicFee;

        // 계산
        time -= basicTime;
        if (time <= 0) return totalFee;

        double doubleTime = time;
        totalFee += (int) (Math.ceil(doubleTime/unitTime) * unitFee);

        return totalFee;
    }
}