# [프로그래머스] Lv 3. [1차] 추석 트래픽
# 문제 설명
이번 추석에도 시스템 장애가 없는 명절을 보내고 싶은 어피치는 서버를 증설해야 할지 고민이다.
장애 대비용 서버 증설 여부를 결정하기 위해 작년 추석 기간인 9월 15일 로그 데이터를 분석한 후 초당 최대 처리량을 계산해보기로 했다.
초당 최대 처리량은 요청의 응답 완료 여부에 관계없이 임의 시간부터 1초(=1,000밀리초)간 처리하는 요청의 최대 개수를 의미한다.
# 입력형식
solution
함수에 전달되는lines
배열은 개의 로그 문자열로 되어 있으며, 각 로그 문자열마다 요청에 대한 응답완료시간 S와 처리시간 T가 공백으로 구분되어 있다.- 응답완료시간 S는 작년 추석인 2016년 9월 15일만 포함하여 고정 길이
2016-09-15 hh:mm:ss.sss
형식으로 되어 있다. - 처리시간 T는
0.1s
,0.312s
,2s
와 같이 최대 소수점 셋째 자리까지 기록하며 뒤에는 초 단위를 의미하는s
로 끝난다. - 예를 들어, 로그 문자열
2016-09-15 03:10:33.020 0.011s
은 "2016년 9월 15일 오전 3시 10분 33.010초"부터 "2016년 9월 15일 오전 3시 10분 33.020초"까지 "0.011초" 동안 처리된 요청을 의미한다. (처리시간은 시작시간과 끝시간을 포함) - 서버에는 타임아웃이 3초로 적용되어 있기 때문에 처리시간은 이다. lines 배열은 응답완료시간 S를 기준으로 오름차순 정렬되어 있다.
# 출력 양식
solution
함수에서는 로그 데이터lines
배열에 대해 초당 최대 처리량을 리턴한다.
# 입출력 예제
# 예제1
입력: [
"2016-09-15 01:00:04.001 2.0s",
"2016-09-15 01:00:07.000 2s"
]출력: 1
# 예제2
입력: [ "2016-09-15 01:00:04.002 2.0s", "2016-09-15 01:00:07.000 2s" ]
출력: 2
# 예제3
입력: [ "2016-09-15 20:59:57.421 0.351s", "2016-09-15 20:59:58.233 1.181s", "2016-09-15 20:59:58.299 0.8s", "2016-09-15 20:59:58.688 1.041s", "2016-09-15 20:59:59.591 1.412s", "2016-09-15 21:00:00.464 1.466s", "2016-09-15 21:00:00.741 1.581s", "2016-09-15 21:00:00.748 2.31s", "2016-09-15 21:00:00.966 0.381s", "2016-09-15 21:00:02.066 2.62s" ]
출력: 7
# 문제 풀이
- 제일 단순하게 드는 생각은 0.001초 단위로 0.001~1.000, 0.002~1.001, 0.003~1.002 이런식으로 구간을 만들어서 for문을 돌리는 것을 생각했으나 너무 비효율적이다.
- 특정 로그가 종료되면서 시작되는 1초 구간의 로그 개수를 확인해서 가장 많이 나온 구간의 로그 개수를 return한다.
# 코드 구현
- 각각 로그의 시작시간과 끝시간, 처리시간을 실수(double)로 변환하여 저장한다.
- 각각 로그의 끝시간 + 1 보다 시작시간이 빠르면서 각각 로그의 끝시간과 같거나 늦게 끝난 로그들의 수를 카운트한다.
- 가장 카운트가 많은 값을 return한다.
# Java
class Solution {
public int solution(String[] lines) {
int answer = 0;
int count = lines.length;
double[] durations = new double[count]; // 처리시간 배열
double[] endTimes = new double[count]; // 끝시간 배열
double[] startTimes = new double[count]; // 시작시간 배열
for(int i=0; i<count; i++) {
String[] lineItems = lines[i].split(" ");
// s제거하여 (0.000s -> 0.000) double로 변환하여 배열에 저장
durations[i] = Double.parseDouble(lineItems[2].replace("s",""));
String[] times = lineItems[1].split("[:|.]");
// 계산 편의를 위해 시 * 3600 + 분 * 60 + 초 + 밀리조로 시작시간을 배열에 저장한다.
endTimes[i] = Double.parseDouble(times[0]) * 3600
+ Double.parseDouble(times[1]) * 60
+ Double.parseDouble(times[2])
+ Double.parseDouble(times[3]) / 1000;
// 처리시간은 시작시간과 끝시간을 포함하고 있으므로
// 끝시간에서 처리시간을 뺀 후, 0.001초를 더해준다.
startTimes[i] = endTimes[i] - durations[i] + .001;
}
for(int i=0; i<count; i++) {
int sameTimeCount = 0;
for(int j=0; j<count; j++) {
// 끝시간~끝시간+1안에 다른 로그가 겹치면 카운트 추가
if(endTimes[i] + 1 > startTimes[j] && endTimes[i] <= endTimes[j]) {
sameTimeCount++;
}
}
if(sameTimeCount > answer) {
answer = sameTimeCount;
}
}
return answer;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42