https://school.programmers.co.kr/learn/courses/30/lessons/92341
프로그래머스
코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.
programmers.co.kr
풀이
주차장의 요금표와 차량이 들어오고(입차) 나간(출차) 기록이 주어졌을 때, 차량별로 주차 요금을 계산해야 한다.
이 때 차는 여러번 입출차를 할 수 있으므로, 각 차의 누적 주차 시간을 계산해서 최종적으로 요금을 계산해야 한다.
먼저 문제를 풀기위한 자료구조는 다음과 같다.
차 번호는 고유하므로 차 번호를 Key로, 차의 정보를 Value로 하는 Map을 생성한다.
static class Car {
int number; // 차 번호
String inDate; // 최근 입차 시각
int time = 0; // 누적 시간
boolean flag = false; // 입차만 했으면 false, 출차까지 했으면 true
public Car(int number, String inDate) {
this.number = number;
this.inDate = inDate;
}
}
HashMap<Integer, Car> cars = new HashMap<>();
또한 차량 번호가 작은 자동차부터 주차 요금을 계산하여 출력해야 하므로 이를 위한 자료구조도 생성한다.
static class CarCost implements Comparable<CarCost> {
int number; // 차 번호
int cost; // 요금
public CarCost(int number, int cost) {
this.number = number;
this.cost = cost;
}
@Override
public int compareTo(CarCost o) {
return this.number - o.number;
}
}
ArrayList<CarCost> carCosts = new ArrayList<>();
로직
1. 입차
- 이미 입출차 한 전적이 있는 차의 경우, cars에서 해당 Car 객체를 조회하여 입차 시각과 flag를 변경하고 cars에 다시 넣는다.
- 새로 입차하는 차의 경우, 새로운 Car 객체를 생성하여 cars에 추가한다.
2. 출차
- cars에서 해당 Car 객체를 조회하여 입차 시각을 가져와 주차 시간(분 단위)을 구한다.
- 해당 Car 객체의 time(누적 주차 시간)을 업데이트한 후 cars에 추가한다.
3. records(입출차 내역)에 따라 모두 처리한 후, 입차만 한 차의 경우를 찾아 23:59에 출차한 것으로 간주하여 누적 시간을 업데이트한다.
4. cars로부터 carCosts를 생성하여 각 차의 요금을 계산한 후 정렬한다.
5. carCosts를 사용하여 answer에 각 차의 요금을 저장한다.
코드
import java.util.*;
class Solution {
static class Car {
int number; // 차 번호
String inDate; // 최근 입차 시각
int time = 0; // 누적 시간
boolean flag = false; // 입차만 했으면 false, 출차까지 했으면 true
public Car(int number, String inDate) {
this.number = number;
this.inDate = inDate;
}
}
static class CarCost implements Comparable<CarCost> {
int number; // 차 번호
int cost; // 요금
public CarCost(int number, int cost) {
this.number = number;
this.cost = cost;
}
@Override
public int compareTo(CarCost o) {
return this.number - o.number;
}
}
public int[] solution(int[] fees, String[] records) {
HashMap<Integer, Car> cars = new HashMap<>();
for (String record: records) {
String[] datas = record.split(" ");
int number = Integer.parseInt(datas[1]);
if (datas[2].equals("IN")) {
if (cars.containsKey(number)) { // 이미 입출차 한 전적이 있는 경우
Car car = cars.get(number);
car.inDate = datas[0]; // 입차 시각 변경
car.flag = false; // flag 변경
cars.put(number, car);
} // 새로 입차하는 경우
else cars.put(number, new Car(number, datas[0]));
}
else if (datas[2].equals("OUT")) {
String inDate = cars.get(number).inDate;
int time = caculateTime(inDate, datas[0]);
Car car = cars.get(number);
car.time += time; // 누적 시간 업데이트
car.flag = true; // flag 변경
cars.put(number, car);
}
}
// 입차만 한 차의 경우 23:59에 출차한 것으로 간주하여 누적 시간 업데이트
for (int number: cars.keySet()) {
Car car = cars.get(number);
if (car.flag) continue;
int time = caculateTime(car.inDate, "23:59");
car.time += time; // 누적 시간 업데이트
car.flag = true; // flag 변경
cars.put(number, car);
}
// cars로부터 carCosts를 생성하여 각 차의 요금 계산
ArrayList<CarCost> carCosts = new ArrayList<>();
for (int number: cars.keySet()) {
Car car = cars.get(number);
int cost = calculateCost(car.time, fees);
carCosts.add(new CarCost(number, cost));
}
Collections.sort(carCosts);
int[] answer = new int[carCosts.size()];
for (int i = 0; i < answer.length; i++) {
answer[i] = carCosts.get(i).cost;
}
return answer;
}
static int caculateTime(String inDate, String outDate) {
String[] inDates = inDate.split(":");
String[] outDates = outDate.split(":");
int inHour = Integer.parseInt(inDates[0]);
int inMinute = Integer.parseInt(inDates[1]);
int outHour = Integer.parseInt(outDates[0]);
int outMinute = Integer.parseInt(outDates[1]);
return (outHour * 60 + outMinute) - (inHour * 60 + inMinute);
}
static int calculateCost(int time, int[] fees) {
if (time <= fees[0]) {
return fees[1];
}
int diffMinute = time - fees[0];
return (int)(fees[1] + fees[3] * (Math.ceil((double)diffMinute/fees[2])));
}
}
다른 풀이 1
차량번호가 작은 순대로 정렬하여 주차 요금을 계산하기 위한 자료구조 없이 HashMap 대신
TreeMap을 사용하면, key 순대로 자동 정렬된다.
import java.util.*;
class Solution {
static class Car {
int number; // 차 번호
String inDate; // 최근 입차 시각
int time = 0; // 누적 시간
boolean flag = false; // 입차만 했으면 false, 출차까지 했으면 true
public Car(int number, String inDate) {
this.number = number;
this.inDate = inDate;
}
}
public int[] solution(int[] fees, String[] records) {
TreeMap<Integer, Car> cars = new TreeMap<>();
for (String record: records) {
String[] datas = record.split(" ");
int number = Integer.parseInt(datas[1]);
if (datas[2].equals("IN")) {
if (cars.containsKey(number)) { // 이미 입출차 한 전적이 있는 경우
Car car = cars.get(number);
car.inDate = datas[0]; // 입차 시각 변경
car.flag = false; // flag 변경
cars.put(number, car);
} // 새로 입차하는 경우
else cars.put(number, new Car(number, datas[0]));
}
else if (datas[2].equals("OUT")) {
String inDate = cars.get(number).inDate;
int time = caculateTime(inDate, datas[0]);
Car car = cars.get(number);
car.time += time; // 누적 시간 업데이트
car.flag = true; // flag 변경
cars.put(number, car);
}
}
// 입차만 한 차의 경우 23:59에 출차한 것으로 간주하여 누적 시간 업데이트
for (int number: cars.keySet()) {
Car car = cars.get(number);
if (car.flag) continue;
int time = caculateTime(car.inDate, "23:59");
car.time += time; // 누적 시간 업데이트
car.flag = true; // flag 변경
cars.put(number, car);
}
// cars로부터 각 차의 요금 계산
int[] answer = new int[cars.size()];
int idx = 0;
for (int key: cars.keySet()) {
Car car = cars.get(key);
int cost = calculateCost(car.time, fees);
answer[idx++] = cost;
}
return answer;
}
static int caculateTime(String inDate, String outDate) {
String[] inDates = inDate.split(":");
String[] outDates = outDate.split(":");
int inHour = Integer.parseInt(inDates[0]);
int inMinute = Integer.parseInt(inDates[1]);
int outHour = Integer.parseInt(outDates[0]);
int outMinute = Integer.parseInt(outDates[1]);
return (outHour * 60 + outMinute) - (inHour * 60 + inMinute);
}
static int calculateCost(int time, int[] fees) {
if (time <= fees[0]) {
return fees[1];
}
int diffMinute = time - fees[0];
return (int)(fees[1] + fees[3] * (Math.ceil((double)diffMinute/fees[2])));
}
}
다른 풀이 2
- Car 객체를 따로 생성할 필요없이 (차번호, 누적 주차 시간)을 Key, Value로 하는 TreeMap<String, Integer> cars를 생성한다.
- 입차하는 경우에는 -, 출차하는 경우에는 +를 하여 누적 주차 시간을 업데이트한다.
- 추후 주차 요금을 계산하기 전에 입차만 한 차의 경우에는 1439분(23:59)을 더해야 한다.
import java.util.*;
class Solution {
public int[] solution(int[] fees, String[] records) {
TreeMap<String, Integer> cars = new TreeMap<>();
for (String record: records) {
String[] datas = record.split(" ");
String number = datas[1];
if (datas[2].equals("IN")) { // 입차
int time = calculateTime(datas[0]);
cars.put(number, cars.getOrDefault(number, 0) - time);
}
else if (datas[2].equals("OUT")) { // 출차
int time = calculateTime(datas[0]);
cars.put(number, cars.getOrDefault(number, 0) + time);
}
}
// cars로부터 각 차의 요금 계산
int[] answer = new int[cars.size()];
int idx = 0;
for (String number: cars.keySet()) {
int time = cars.get(number);
if (time <= 0) { // 입차만 한 차의 경우 23:59에 출차한 것으로 간주
time += 1439;
}
answer[idx++] = calculateCost(time, fees);
}
return answer;
}
static int calculateTime(String date) {
String[] dates = date.split(":");
return Integer.parseInt(dates[0]) * 60 + Integer.parseInt(dates[1]);
}
static int calculateCost(int time, int[] fees) {
if (time <= fees[0]) {
return fees[1];
}
int diffMinute = time - fees[0];
return (int)(fees[1] + fees[3] * (Math.ceil((double)diffMinute/fees[2])));
}
}
'Algorithm 문제 풀이 > 프로그래머스' 카테고리의 다른 글
[프로그래머스] Lv.2 : 롤케이크 자르기 - 자바[Java] (0) | 2023.09.07 |
---|---|
[프로그래머스] Lv.2 : k진수에서 소수 개수 구하기 - 자바[Java] (0) | 2023.09.06 |
[프로그래머스] Lv.2 : 소수 찾기 - 자바[Java] (0) | 2023.08.29 |
[프로그래머스] Lv.2 : [1차] 프렌즈4블록 - 자바[Java] (0) | 2023.08.25 |
[프로그래머스] Lv.2 : 더 맵게 - 자바[Java] (0) | 2023.08.22 |