링크

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

 

프로그래머스

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

programmers.co.kr

 

문제

 

풀이

1. 누적 입/출차 시간 계산
2. 출차된 내역 없는 차량 시간 계산
3. 차량 번호 정렬
4. 요금 정산

순서로 문제를 풀었습니다.
Int[] fees: 각 원소는 "기본 시간(분), 기본 요금(원), 단위 시간(분), 단위 요금(원)" 형식의 숫자입니다.
String[] records: 각 원소는 "시각, 차량번호, 내역" 형식의 문자열입니다.

 

1. 누적 입/출차 시간 계산
records 배열만큼 반복문을 이용했습니다.
split 함수를 이용하여 records 각 원소의  "시각, 차량번호, 내역"을 구분하였습니다.

// 1.누적 입/출차 시간 계산
for (String record : records) {
	String[] arr = record.split(" ");
    
}


parkingTime 이라는 함수를 만들어서 입/출차 시간을 계산했습니다.
record 매개변수는 각 원소의 "시각, 차량번호, 내역"을 순서대로 갖고 있기 때문에 
시각: time
차량번호: carNumber
내역: inOut
으로 분류했습니다.

내역이 IN 이면 Map에 해당 데이터를 저장하고
Out 이면 저장되어 있는 데이터를 꺼내서
IN 시간과 OUT 시간을 계산 후 누적 주차 시간을 구했습니다.

public void parkingTime(String[] record) {
    String time = record[0];
    String carNumber = record[1];
    String inOut = record[2];

    if ("IN".equals(inOut)) {
        parkingMap.put(carNumber, time);
        return;
    }

    int inTime = toMinutes(parkingMap.get(carNumber).split(":"));
    int outTime = toMinutes(time.split(":"));
    int useTime = outTime - inTime;

    parkingMap.remove(carNumber);
    if (resultMap.containsKey(carNumber)) {
        resultMap.put(carNumber, resultMap.get(carNumber) + useTime);
        return;
    }
    resultMap.put(carNumber, useTime);
}
// 1.누적 입/출차 시간 계산
for (String record : records) {
    String[] arr = record.split(" ");
    parkingTime(arr);
}


중복을 제외한 입차된 차량 수를 구하기 위해 Set을 이용하였습니다.
Set에 차량번호가 이미 있다면 카운트를 올리지 않고, 차량번호가 없을 경우만 카운트를 올립니다.

// 1.누적 입/출차 시간 계산
Set<String> car = new HashSet<>();
int cnt = 0;
for (String record : records) {
    String[] arr = record.split(" ");
    parkingTime(arr);
    if (car.contains(arr[1])) continue;
    car.add(arr[1]);
    cnt++;
}

 

2. 출차된 내역 없는 차량 시간 계산
records 배열에 있는 입/출차 시간을 계산 후 
아직 출차되지 않은 차가 있다면 23:59로 계산하여 출차시킵니다.
출차되지 않은 차량 기준은 내역이 IN 이면 Map에 해당 데이터를 저장하고 OUT이 없어서 꺼내지 못한 데이터입니다.
lastTime이라는 함수에  구현하였습니다.
parkingMap은 IN 데이터를 저장해놓은 HashMap입니다.

// 2.출차된 내역 없는 차량 시간 계산
for (Map.Entry<String, String> map : parkingMap.entrySet()) {
    lastTime(map.getKey(), map.getValue());
}
public void lastTime(String carNumber, String time) {

    int inTime = toMinutes(time.split(":"));
    int outTime = toMinutes("23:59".split(":"));
    int useTime = outTime - inTime;

    if (resultMap.containsKey(carNumber)) {
        resultMap.put(carNumber, resultMap.get(carNumber) + useTime);
        return;
    }
    resultMap.put(carNumber, useTime);
}

 

3. 차량 번호 정렬
입/출차 시간이 계산된 Map을 list로 변환하여 차량 번호 순서대로 정렬했습니다.
정렬하는 이유는 반환하는 차량 번호를 차량 번호 순서대로 해야 하기 때문입니다.

// 3.차량 번호 정렬
List<String> keyList = new ArrayList<>(resultMap.keySet());
Collections.sort(keyList);

 

4. 요금 정산
입/출차 시간이 계산된 데이터와 차량 번호 순서로 정렬되어 있으니
요금 정산 후 반환해주면 완료입니다.
반환할 배열을 생성합니다.
배열 수는 처음에 중복을 제외한 입차 된 차량 수를 담은 cnt라는 변수를 사용합니다.

int[] answer = new int[cnt];

반복문을 사용하여 차량 번호 순서로 요금 정산을 해줍니다.
요금 정산은 calculate라는 함수를 만들어서 계산했습니다.

// 4.요금 정산
int[] answer = new int[cnt];
int index = 0;
for (String key : keyList) {
    answer[index] = calculate(fees, resultMap.get(key));
    index++;
}

calculate의 매개변수는 fees(요금표)와 parkingTime(누적 주차 시간)을 받습니다.
만약 누적 주차 시간이 기본 이용 시간보다 적거나 같으면 기본 이용 요금을 지불합니다.
누적 주차 시간이 기본 이용 시간보다 많다면 기본 이용 시간을 제외 후 나머지 시간을 계산합니다.
단위 시간만큼 몫을 구하고 나머지 시간이 있다면 단위시간 1회 더 해당하는 것으로 간주합니다.

ex. 
단위 시간: 10분
단위 요금: 100원
이용시간: 11분
지불금액: 200원

public int calculate(int[] fees, int parkingTime) {
    int defaultTime = fees[0];
    int defaultPay = fees[1];
    int time = fees[2];
    int pay = fees[3];

    int useTime = parkingTime;

    if (defaultTime >= useTime) {
        return defaultPay;
    }

    useTime -= defaultTime;

    int quotient = useTime / time;

    if (quotient == 0) {
        quotient = 1;
        return defaultPay + (pay * quotient);
    }

    if (((quotient * time) - useTime) != 0) {
        quotient += 1;
    }

    return defaultPay + (pay * quotient);
}

 

전체 코드

HashMap<String, String> parkingMap = new HashMap<>();
HashMap<String, Integer> resultMap = new HashMap<>();
public int[] solution(int[] fees, String[] records) {

    // 1.누적 입/출차 시간 계산
    Set<String> car = new HashSet<>();
    int cnt = 0;
    for (String record : records) {
        String[] arr = record.split(" ");
        parkingTime(arr);
        if (car.contains(arr[1])) continue;
        car.add(arr[1]);
        cnt++;
    }

    // 2.출차된 내역 없는 차량 시간 계산
    for (Map.Entry<String, String> map : parkingMap.entrySet()) {
        lastTime(map.getKey(), map.getValue());
    }

    // 3.차량 번호 정렬
    List<String> keyList = new ArrayList<>(resultMap.keySet());
    Collections.sort(keyList);


    // 4.요금 정산
    int[] answer = new int[cnt];
    int index = 0;
    for (String key : keyList) {
        answer[index] = calculate(fees, resultMap.get(key));
        index++;
    }

    return answer;
}

public void parkingTime(String[] record) {
    String time = record[0];
    String carNumber = record[1];
    String inOut = record[2];

    if ("IN".equals(inOut)) {
        parkingMap.put(carNumber, time);
        return;
    }

    int inTime = toMinutes(parkingMap.get(carNumber).split(":"));
    int outTime = toMinutes(time.split(":"));
    int useTime = outTime - inTime;

    parkingMap.remove(carNumber);
    if (resultMap.containsKey(carNumber)) {
        resultMap.put(carNumber, resultMap.get(carNumber) + useTime);
        return;
    }
    resultMap.put(carNumber, useTime);
}

public int toMinutes(String[] time) {
    int hour = Integer.parseInt(time[0]) * 60;
    int minute = Integer.parseInt(time[1]);
    return hour + minute;
}

public void lastTime(String carNumber, String time) {

    int inTime = toMinutes(time.split(":"));
    int outTime = toMinutes("23:59".split(":"));
    int useTime = outTime - inTime;

    if (resultMap.containsKey(carNumber)) {
        resultMap.put(carNumber, resultMap.get(carNumber) + useTime);
        return;
    }
    resultMap.put(carNumber, useTime);
}

public int calculate(int[] fees, int parkingTime) {
    int defaultTime = fees[0];
    int defaultPay = fees[1];
    int time = fees[2];
    int pay = fees[3];

    int useTime = parkingTime;

    if (defaultTime >= useTime) {
        return defaultPay;
    }

    useTime -= defaultTime;

    int quotient = useTime / time;

    if (quotient == 0) {
        quotient = 1;
        return defaultPay + (pay * quotient);
    }

    if (((quotient * time) - useTime) != 0) {
        quotient += 1;
    }

    return defaultPay + (pay * quotient);
}

 

후기

* 난이도 (5점 만점)

5 : 풀 줄 알면 기업 코딩 테스트는 문제없음.

4 : 평균적인 기업 코딩 테스트의 중간 이상.

3 : 평균적인 기업 코딩테스트의 쉬운 문제.

2 : 알고리즘 문제를 연습하고 있다면 풀 수 있는 문제.

1 : 시간이 오래 걸리지 않고, 누구나 풀 수 있는 문제.

 

시간 계산(시, 분)에 대해 겁먹지 않는다면 차분하게 풀 수 있는 문제입니다.
감사합니다.

+ Recent posts