코딩 테스트/프로그래머스

프로그래머스 - 추석 트래픽 문제 (자바)

programmers.co.kr/learn/courses/30/lessons/17676

 

코딩테스트 연습 - [1차] 추석 트래픽

입력: [ "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-1

programmers.co.kr

기본적으로 문자열이 종료시점을 기준으로 정렬되서 넘어오기 때문에

가장 빨리 끝나는 로그부터 비교해 나아가면됩니다.

우선 이전 로그의 종료시점을 구합니다.

로그배열을 순회하면서 종료시점 + 1초 보다 빨리 시작하는 로그를 찾아서 count를 올려주면 됩니다.

 

주의할점으로

1. 밀리세컨드까지 파싱해야한다.

2. 시작과 종료 시간을 정확히 계산해야한다. 

 - 주석으로 도 적혀 있지만 2016-09-15 01:00:07.000 2s01:00:05.001 ~ 01:00:07.000에서 2초 동안 처리되므로

사실상 로그의 종료시간 - 걸리 초 + 0.001초 라고 보면된다. (저는 0.001초를 안해서 많이 고민했던 ...)

3. 이전의 종료시간과 1초 차이보다 적게 나면 카운트를 올린다. 

 - 주석으로도 적혀 있지만 1초범위라고 1000을 더하고 >= 고 하게 되면 안됩니다. 

 - 1부터 10개를 가진다고하면 1, 2, 3, 4, ,5, 6, 7, 8, 9, 10인데 1 + 10 은 11이기 때문이죠.

 - 위와 동일하게 1초부터 1초의 범위를 가진다면 1,000 ~ 1.999 까지 라는 겁니다.

import java.text.SimpleDateFormat;
import java.util.*;

class Solution {
    public static int solution(String[] lines) throws Exception {
        SimpleDateFormat format = new SimpleDateFormat("HH:mm:ss.SSS");

        int[] counts = new int[lines.length];
        int max = 0;

        for(int i=0; i<lines.length; i++) {
            // 이전 로그의 완료 시점
            String[] pre = lines[i].split(" ");
            Date preEndDate = format.parse(pre[1]);
            long preEnd = preEndDate.getTime();

            // 해당 로그 보다 늦게 종료되는 로그 체크
            for (int j = i ; j < lines.length; j++) {
                // 다음 로그의 시작시점
                String[] next = lines[j].split(" ");
                Date nextEndDate = format.parse(next[1]);
                double sec = Double.parseDouble(next[2].substring(0, next[2].length()-1)); // 처리 시간

                // 다음로그의 종료시점 - 처리 초 + 1;
                // 문제에서 보면 알듯 2016-09-15 01:00:07.000 2s는
                // 01:00:05.001 ~ 01:00:07.000에서 2초 동안 처리된다.
                // 7,000 - 2,000 + 1 = 5.001
                long nextStart = (long) (nextEndDate.getTime() - sec*1000 + 1);

                // 이전 로그의 종료시점부터 + 1초 범위안에 시작되면 + 1
                // 1부터 10의 범위를 가진다고 하면
                // 1 2 3 4 5 6 7 8 9 10 이렇게 가진다.
                // 1 + 10 = 11 이므로 = 부호를 사용하면 안됨
                if(preEnd + 1000 > nextStart) {
                    counts[i] += 1;
                    max = Math.max(max, counts[i]);
                }
            }
        }
        return max;
    }
}