프로그래머스 2018 KAKAO BLIND RECRUITMENT Level 3 문제 추석 트래픽을 Java를 이용해 풀어보았다.
시간 값을 비교할 때에 편리한 로직을 배우게 됐다.
문제 링크 첨부한다.
https://programmers.co.kr/learn/courses/30/lessons/17676
두 개의 시각을 하나의 구간으로 보고, 두 개의 구간끼리 겹치는지 판별해주기 위한 로직이 필요하다. 나는 처음에 HH:mm:ss.sss
형식 그대로 사용해서 시간끼리 서로 비교할 수 있도록 로직을 짜려 했는데 아무리 생각해도 너무 더러웠다.
알고보니 시간에 60*60*1000 배를 해서 ms
단위로 바꿔주고, 분에는 60*1000배를 해서 ms
단위로 바꿔주는 작업을 시간 + 분 + 초
를 하면 하나의 고유한 시간값을 구할 수 있었다.
하나의 입력값에 대해 작업 종료 시각과 응답 처리 시간을 파싱해서 받은 후에 위와 같은 작업을 통해 작업 시작 시각과 작업 종료 시각을 위와 같이 변환하여 하나의 Info
클래스에 시작 시각과 끝 시각을 담도록 했다.
Info
클래스의 코드는 다음과 같다.
class Info{
int start;
int end;
Info(String line){
String[] split = line.split("\\s");
String endStr = split[1];
String resStr = split[2];
String[] endTimeSplit = endStr.split(":");
int hrs = Integer.parseInt(endTimeSplit[0])*60*60*1000;
int mins = Integer.parseInt(endTimeSplit[1])*60*1000;
int secs = (int)(Double.parseDouble(endTimeSplit[2])*1000);
this.end = hrs + mins + secs;
resStr = resStr.replaceAll("s","");
int resTime = (int)(Double.parseDouble(resStr)*1000);
this.start = this.end - resTime + 1;
}
Info(int start, int end){
this.start = start;
this.end = end;
}
Boolean isOverLap(Info target){
if(target.end < this.start || this.end < target.start) return false;
return true;
}
Integer getStart(){ return this.start; }
}
그럼 이 Info
클래스를 활용해서 입력값으로 주어지는 모든 구간들을 list에 저장해준 후에 시작 시각 기준으로 오름차순 정렬을 해주면 된다.
이를 코드로 표현하면 다음과 같다.
ArrayList<Info> list = new ArrayList<>();
for(String line: lines)
list.add(new Info(line));
list.sort(Comparator.comparing(Info::getStart));
list에 있는 모든 구간에 대해 시작 시각으로부터 1초, 끝 시각으로부터 1초까지의 새로운 Info
객체를 생성해서 list의 모든 구간에 대해 몇 개나 겹치는지 조사를 하며 겹친 개수들을 또다른 list에 저장해준 후에 그 중 가장 큰 값을 꺼내면 문제에서 요구하는 답이다.
이를 코드로 표현하면 다음과 같다.
ArrayList<Integer> overlap = new ArrayList<>();
for(Info cur: list){
// Info target1 = new Info(cur.start, cur.start+999);
Info target2 = new Info(cur.end, cur.end+999);
// int target1OverLapNum = 0;
int target2OverLapNum = 0;
for(Info test: list){
// if(test.isOverLap(target1)) target1OverLapNum++;
if(test.isOverLap(target2)) target2OverLapNum++;
}
// if(overlap.indexOf(target1OverLapNum)<0) overlap.add(target1OverLapNum);
if(overlap.indexOf(target2OverLapNum)<0) overlap.add(target2OverLapNum);
}
Collections.sort(overlap, Collections.reverseOrder());
return overlap.get(0);
시작 시각으로부터 1초까지의 구간인 target1
을 주석 처리한 이유는 어차피 필요가 없기 때문이다.
카카오 테크 블로그의 해설을 참고하면 시작과 끝에 대해 모두 1초 지난 구간을 조사해야 된다고 나와있지만, 생각해보니 끝으로부터 1초까지의 구간만 확인해도 다 커버가 될 거라는 생각이 들었고 실제로 수행해보니 모든 테스트 케이스를 다 통과했다.
오늘 문제 풀이는 사실 말보다도 그냥 값을 비교한 후에 겹치는 개수만 뽑아내면 되는 거기 때문에 ms
단위까지 포함하는 시간을 HH:mm:ss.sss
형식 그대로가 아닌 변환된 형태로 저장해주는 것이 가장 주요했다.