코딩 테스트 [프로그래머스] - 주차 요금 계산

유의선·2024년 3월 11일

문제 링크

중복을 허용하지 않고 <key, value> 쌍으로 데이터를 저장하는 HashMap의 특징을 이용해 풀었다.


전체 코드는 다음과 같다.

import java.util.*;

class Solution {
    static int LAST = (23 * 60) + 59;
    
    public int[] solution(int[] fees, String[] records) {
        int[] answer;
        HashMap<String, Integer> hashMap = new HashMap<>();
        Stack<Integer> stack = new Stack<>();
        
        Arrays.sort(records, new Comparator<String>(){
            @Override
            public int compare(String o1, String o2){
                String[] o1a = o1.split(" ");
                String[] o2a = o2.split(" ");
                
                return o1a[1].compareTo(o2a[1]);
            }
        });
        
        String[] start = records[0].split(" ");
        String before = start[1];
        
        for(int i = 0; i < records.length; i++){
            String[] tmp = records[i].split(" ");
            
            String[] timeString = tmp[0].split(":");
            int time = (Integer.parseInt(timeString[0]) * 60) + Integer.parseInt(timeString[1]);
            String carNum = tmp[1];
            String type = tmp[2];
            
            if(type.equals("IN")){
                if(stack.isEmpty()){
                    stack.add(time);
                }else{
                    int timeStart = stack.pop();
                    int parkedTime = LAST - timeStart;
                    int stackedTime = hashMap.getOrDefault(before, 0);
                    hashMap.put(before, stackedTime + parkedTime);
                    
                    stack.add(time);
                }
            }else if(type.equals("OUT")){
                int timeStart = stack.pop();
                int parkedTime = time - timeStart;
                int stackedTime = hashMap.getOrDefault(carNum, 0);
                hashMap.put(carNum, stackedTime + parkedTime);
            }
            
            before = carNum;
        }
        
        if(!stack.isEmpty()){
            int timeStart = stack.pop();
            int parkedTime = LAST - timeStart;
            int stackedTime = hashMap.getOrDefault(before, 0);
            hashMap.put(before, stackedTime + parkedTime);
        }
        
        answer = new int[hashMap.size()];
        ArrayList<String> arrayList = new ArrayList<>(hashMap.keySet());
        Collections.sort(arrayList);
        
        for(int i = 0; i < arrayList.size(); i++){
            String key = arrayList.get(i);
            int time = hashMap.get(key);
            int fee = 0;
            
            time -= fees[0];
            fee += fees[1];
            
            if(time > 0){
                double exceedTime = time / (double)fees[2];
                int exceedFee = (int)Math.ceil(exceedTime) * fees[3];
                fee += exceedFee;
            }
            
            answer[i] = fee;
        }
        
        return answer;
    }
}

출차된 내역이 없다면 출차된 것으로 간주할 시간인 LAST
차량의 번호를 key로, 총 주차 시간을 value로 저장하는 HashMap,
차량이 주차를 시작한 시간을 저장할 Stack을 만들었다.

class Solution {
    static int LAST = (23 * 60) + 59;
    
    public int[] solution(int[] fees, String[] records) {
        int[] answer;
        HashMap<String, Integer> hashMap = new HashMap<>();
        Stack<Integer> stack = new Stack<>();

차량의 주차 시간을 계산할 때 여러 차량을 동시에 계산하는 것 보다 한 차량마다 계산하는 것이 더 편하기에records 배열을 같은 차량 번호끼리 뭉치도록 정렬하였다.

"주차시간 차량번호 내역" 형식으로 저장된 문자열 records를 차량번호 기준으로 오름차순 정렬시켰다.

        Arrays.sort(records, new Comparator<String>(){
            @Override
            public int compare(String o1, String o2){
                String[] o1a = o1.split(" ");
                String[] o2a = o2.split(" ");
                
                return o1a[1].compareTo(o2a[1]);
            }
        });

현재 보는 차량의 이전 차량을 저장하는 before을 첫 번째 차량으로 초기화했다.

        String[] start = records[0].split(" ");
        String before = start[1];

records의 길이만큼 아래 내용을 반복한다.

        for(int i = 0; i < records.length; i++){
            ...
        }

records에서 기록을 하나씩 가져와
시간, 차량번호, 기록을 저장한다.
이 때 시간은 분단위로 저장한다.

        for(int i = 0; i < records.length; i++){
            String[] tmp = records[i].split(" ");
            
            String[] timeString = tmp[0].split(":");
            int time = (Integer.parseInt(timeString[0]) * 60) + Integer.parseInt(timeString[1]);
            String carNum = tmp[1];
            String type = tmp[2];
            
            ...
            
		}

기록을 확인해 주차인지 출차인지 확인한다.

            if(type.equals("IN")){
                ...
            }else if(type.equals("OUT")){
                ...
            }

만약 주차라면 지금 stack에 주차된 차가 있는지 확인한다.

주차된 차량이 있다는 것은 이전 차량이 주차한 채로 끝났다는 것이다.
출차된 내역이 없다면 LAST를 출차한 시간으로 간주하므로 stack에서 주차한 시간을 가져와 LAST에 그 수를 빼 주차한 시간을 계산한다.
그 후 before로 이전 차량의 번호를 얻어 HashMap의 key값으로 검색해 누적 주차 시간을 얻고,
이전 차량의 누적 주차 시간에 지금 계산한 주차 시간을 더한 값을HashMap에 넣는다.

그 후 빈 stack에 지금 차량의 주차한 시간을 집어넣는다.

만약 주차된 차량이 없다면 바로 지금 차량의 주차한 시간을 집어넣는다.

            if(type.equals("IN")){
                if(stack.isEmpty()){
                    stack.add(time);
                }else{
                    int timeStart = stack.pop();
                    int parkedTime = LAST - timeStart;
                    int stackedTime = hashMap.getOrDefault(before, 0);
                    hashMap.put(before, stackedTime + parkedTime);
                    
                    stack.add(time);
                }
            }else if(type.equals("OUT")){
                ...
            }

만약 출차라면

stack에 저장되어있는 주차 시작 시간을 출차 시간에서 뺀다.
그 후 HashMap의 key값으로 검색해 누적 주차 시간을 얻고,
누적 주차 시간에 지금 계산한 주차 시간을 더한 값을HashMap에 넣는다.

            if(type.equals("IN")){
                ...
                }
            }else if(type.equals("OUT")){
                int timeStart = stack.pop();
                int parkedTime = time - timeStart;
                int stackedTime = hashMap.getOrDefault(carNum, 0);
                hashMap.put(carNum, stackedTime + parkedTime);
            }

계산 후엔 이전 차량 값을 현재 차량 값으로 바꿔준다.

        for(int i = 0; i < records.length; i++){
            
            ...
            
            before = carNum;
        }

반복문이 끝난 후에 stack이 비어있는지 확인한다.
만약 비어있지 않다면 마지막 차량이 출차하지 않은 채로 끝났다는 뜻이므로
LAST에 출차한것으로 간주해 계산한다.

        if(!stack.isEmpty()){
            int timeStart = stack.pop();
            int parkedTime = LAST - timeStart;
            int stackedTime = hashMap.getOrDefault(before, 0);
            hashMap.put(before, stackedTime + parkedTime);
        }

정답 배열의 크기를 차량 수인 HashMap의 크기로 초기화한다.
ArrayList를 만들어 HashMap의 key값을 저장하고, 오름차순으로 정렬한다.

        answer = new int[hashMap.size()];
        ArrayList<String> arrayList = new ArrayList<>(hashMap.keySet());
        Collections.sort(arrayList);

ArrayList의 크기만큼 반복하며 오름차순으로 정렬된 차량 번호를 하나씩 가져온다.
차량 번호로 HashMap에 저장되있는 차량의 총 주차 시간을 가져오고
fees배열에 저장되있는 주차 요금에 따라서 주차 요금을 계산해 정답 배열에 넣어준다.

        for(int i = 0; i < arrayList.size(); i++){
            String key = arrayList.get(i);
            int time = hashMap.get(key);
            int fee = 0;
            
            time -= fees[0];
            fee += fees[1];
            
            if(time > 0){
                double exceedTime = time / (double)fees[2];
                int exceedFee = (int)Math.ceil(exceedTime) * fees[3];
                fee += exceedFee;
            }
            
            answer[i] = fee;
        }
        
        return answer;

0개의 댓글