코딩테스트-알고리즘/프로그래머스

[프로그래머스/Lv.2] 주차 요금 계산

닉네임생각즁 2024. 2. 22. 02:55

 

 

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

 

프로그래머스

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

programmers.co.kr

 

HashMap을 사용하는 방법도 생각했으나 약간 다르게 풀어보았다

 

1.

	Set<String> set = new HashSet<>(); // 차량 번호 중복 제거
        for(int i = 0 ; i < records.length; i++) {
            String[] str = records[i].split(" ");
            set.add(str[1]);
        }
        List<String> car = new ArrayList<>(set); // 차량 번호 리스트
        Collections.sort(car); // 차량 번호가 작은 자동차순으로 정렬

 

- 먼저 차량 번호 리스트를 만들기 위해 차량 번호만 뽑아서 HashSet에 넣어 중복 제거를 해주었다

- Set을 List로 변환해주면서 오름차순 정렬을 해주었다 최종 답을 낼 때 차량 번호가 작은 순으로 요금을 출력해야하기 때문에 미리 정렬해주고 해당 인덱스에 각각 값을 매치시키려는 생각이었다

 

 

이제부터는 이 차량 번호 리스트를 돌며 각 차량 별로 주차 요금을 계산해 줄 것이다

for(int i = 0; i < car.size(); i++)

 

 

2.

	List<String> inCar = new ArrayList<>(); // 차량 별 입차 시간 리스트
            List<String> outCar = new ArrayList<>(); // 차량 별 출차 시간 리스트
            
            for(int j = 0; j < records.length; j++) {
                String[] str = records[j].split(" ");
                if(str[1].equals(car.get(i))) {
                    if(str[2].equals("IN")) inCar.add(str[0]);
                    else outCar.add(str[0]);
                }       
            }

 

- IN일때는 inCar 리스트에 입차 시간을 넣어주고 OUT일때는 outCar 리스트에 출차 시간을 넣어준다

 

 

3. 누적 주차 시간 계산

	if(outCar.size() == 0) { // #3 같은 경우 (한번 입차하고 출차 기록 없음)
                String[] str = inCar.get(0).split(":");
                parkingTime = endTime - (Integer.parseInt(str[0]) * 60 + Integer.parseInt(str[1]));
            } else {
                for(int x = 0; x < outCar.size(); x++) {
                    String[] inTime = inCar.get(x).split(":");
                    String[] outTime = outCar.get(x).split(":");
                    parkingTime += (Integer.parseInt(outTime[0]) * 60 + Integer.parseInt(outTime[1]))
                        - (Integer.parseInt(inTime[0]) * 60 + Integer.parseInt(inTime[1]));
                                        
                    if(x == outCar.size() - 1 && inCar.size() > outCar.size()) {
                        // 두번 이상 입차했을 때, 마지막 입차에 대한 출차 기록이 없는 경우
                        String[] inLastTime = inCar.get(x + 1).split(":");
                        parkingTime += endTime - (Integer.parseInt(inLastTime[0]) * 60 + Integer.parseInt(inLastTime[1]));
                    }
                }
                
            }

 

- 입차만 있고 출차가 없는 경우가 있기 때문에 오0류 발생을 막기 위해 출차 리스트의 크기를 기준으로 해야한다

1) #3 처럼 딱 한번 입차하고 출차 기록은 없는 경우 출차 리스트 크기가 0이고 이때는 endTime에서 입차 시간을 빼주기만 하면 된다

int endTime = 23 * 60 + 59; // 23시 59분

→ 출차 기록이 없는 경우 23시 59분을 기준으로 계산해줘야하기 때문에 자주 사용할거 같아서 이렇게 endTime을 선언해두었다

 

2) 출차 리스트 크기가 0이 아니라면 출차 시간에서 입차 시간을 빼주면 된다

주의해야할점!! 마지막 입차하고 나서 출차 기록이 없는 경우도 있으므로 만약 입차 리스트 크기가 더 크다면 마지막 입차 기록은 1) 처럼 endTime과 계산해주어야한다

 

 

4. 주차 요금 계산

	if(parkingTime <= defaultTime) {
                result[i] = defaultFee;
            } else {
                result[i] = defaultFee + (int)Math.ceil((double)(parkingTime - defaultTime) / unitTime) * unitFee; 
            }

 

- 누적 추차 시간이 기본 시간을 넘지 않는다면 기본 요금만 내면 되고, 기본 시간을 넘는다면 넘은 만큼 계산해서 더해주는 과정을 거치면 된다

- 차량 번호를 처음에 오름차순으로 정렬하고나서 진행한거기 때문에 주차 요금 결과는 각 인덱스 번호에 맞게 result 배열에 넣어주기만 하면 된다

 

 

최종 코드

import java.util.*;

class Solution {
    public int[] solution(int[] fees, String[] records) {
        
        int defaultTime = fees[0]; // 기본 시간(분)
        int defaultFee = fees[1]; // 기본 요금(원)
        int unitTime = fees[2]; // 단위 시간(분)
        int unitFee = fees[3]; // 단위 요금(원)
        int endTime = 23 * 60 + 59; // 23시 59분
        
        Set<String> set = new HashSet<>(); // 차량 번호 중복 제거
        for(int i = 0 ; i < records.length; i++) {
            String[] str = records[i].split(" ");
            set.add(str[1]);
        }
        List<String> car = new ArrayList<>(set); // 차량 번호 리스트
        Collections.sort(car); // 차량 번호가 작은 자동차순으로 정렬
        // System.out.println(car);
        
        int[] result = new int[car.size()]; 
        
        for(int i = 0; i < car.size(); i++) {
            List<String> inCar = new ArrayList<>(); // 차량 별 입차 시간 리스트
            List<String> outCar = new ArrayList<>(); // 차량 별 출차 시간 리스트
            
            for(int j = 0; j < records.length; j++) {
                String[] str = records[j].split(" ");
                if(str[1].equals(car.get(i))) {
                    if(str[2].equals("IN")) inCar.add(str[0]);
                    else outCar.add(str[0]);
                }       
            }
            // System.out.println(car.get(i));
            // System.out.println(in);
            // System.out.println(out);
        
            int parkingTime = 0;
            
            if(outCar.size() == 0) { // #3 같은 경우 (한번 입차하고 출차 기록 없음)
                String[] str = inCar.get(0).split(":");
                parkingTime = endTime - (Integer.parseInt(str[0]) * 60 + Integer.parseInt(str[1]));
            } else {
                for(int x = 0; x < outCar.size(); x++) {
                    String[] inTime = inCar.get(x).split(":");
                    String[] outTime = outCar.get(x).split(":");
                    parkingTime += (Integer.parseInt(outTime[0]) * 60 + Integer.parseInt(outTime[1]))
                        - (Integer.parseInt(inTime[0]) * 60 + Integer.parseInt(inTime[1]));
                                        
                    if(x == outCar.size() - 1 && inCar.size() > outCar.size()) {
                        // 두번 이상 입차했을 때, 마지막 입차에 대한 출차 기록이 없는 경우
                        String[] inLastTime = inCar.get(x + 1).split(":");
                        parkingTime += endTime - (Integer.parseInt(inLastTime[0]) * 60 + Integer.parseInt(inLastTime[1]));
                    }
                }
                
            }
            
            if(parkingTime <= defaultTime) {
                result[i] = defaultFee;
            } else {
                result[i] = defaultFee + (int)Math.ceil((double)(parkingTime - defaultTime) / unitTime) * unitFee; 
            }
        }
        
        return result;
    }
}