개발/알고리즘

[프로그래머스][2018 KAKAO BLIND RECRUITMENT] 추석 트래픽 (level 3)

nova_dev 2020. 12. 11. 22:57
반응형

문제가 참 어려웠네요. 문제 이해도 쉽고, 풀고 나서 코드는 참 간단한데 구간 내 트래픽을 구할 방법을 못 찾아서 한참 헤매었습니다. Date클래스로 포맷팅 하면 끝날 줄 알았는데 본격적인 문제의 시작은 그다음이더군요. 별의별 생각을 다하다가(밀리세컨드 단위로 늘려야 하나 같은..) 시작점부터 1초까지를 모두 카운트했다가 실패하고, 카카오 해설요청량이 변하는 순간은 각 로그의 시작과 끝뿐임을 알 수 있습니다. 이 말을 키포인트로 풀었습니다.

Traffic 클래스

  • startTime, endTime을 Date의 long형식으로 가지고 있고, float로 processTime(작업시간)을 들고 있습니다.
  • Traffic 생성자에서는 parseLog 메서드를 통해 SimpleDateFormat으로 "yyyy-MM-dd hh:mm:ss.SSS"형식의 데이터로 파싱하여 startTime, endTime을 계산하여 넣습니다. 마찬가지로 s문자열을 잘라내어 Float으로 파싱 하여 processTime에 저장합니다.

getCountMax 메서드

  • startSection ~ endSection (1초)간에 이 값 사이에 있는 트래픽을 찾아냅니다.
    (1) startTime이 startSection보다 크고, startTime이 endSection보다 작은 경우
    (2) endTime이 startSection보다 크고, endTime이 endSection보다 작은 경우
    (3) startTime이 startSection보다 작고, endTime이 startSection보다 큰 경우
    위 세가지 경우일 때 트래픽은 해당 구간 안에 포함되어 있기 때문에 count를 증가시켜, 가장 트래픽이 많은 구간을 찾아냅니다. 이때, 요청량이 변하는 순간은 각 로그의 시작과 끝 + 1초 구간이기 때문에, 해당 구간을 startSection에 넣어 구간을 산정합니다.

    아래 사진의 주황색으로 표시한 부분이 위 (1), (2), (3) 조건에 해당하는 부분입니다.

트래픽 알고리즘 문제

solution

  1. 들어온 Log값을 Traffic 클래스를 통해 파싱하여 startTime, endTime을 저장하고, List에 저장해둡니다.
  2. getCountMax 메서드를 호출하여, startSection에 startTime을 넣은 구간의 최대 카운트를 answer에 넣습니다.
  3. getCountMax 메서드를 호출하여, startSection에 endTime을 넣은 구간의 최대 카운트를 answer에 넣습니다.
  4. 결과를 반환합니다.
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;

class Solution {
    public int solution(String[] lines) {
        int answer = 0;
        List<Traffic> trafficList = new ArrayList<Traffic>();
        for (String line : lines){
            trafficList.add(new Traffic(line));
        }

        // 요청량이 변하는 순간은 각 로그의 시작과 끝뿐이다.
        answer = getCountMax(trafficList, true, answer);
        answer = getCountMax(trafficList, false, answer);

        return answer;
    }
    private int getCountMax (List<Traffic> trafficList, boolean isStart, int maxCount){
        for (int i = 0; i <trafficList.size(); ++i){
            int count = 0;
            long startSection = isStart ? trafficList.get(i).startTime : trafficList.get(i).endTime;
            long endSection = startSection + 1000;

            for (int j = 0; j < trafficList.size(); ++j) {
                if ((startSection <= trafficList.get(j).startTime && trafficList.get(j).startTime < endSection)
                        || (startSection <= trafficList.get(j).endTime && trafficList.get(j).endTime < endSection)
                        || (trafficList.get(j).startTime <= startSection && endSection <= trafficList.get(j).endTime)) {
                    count++;
                }

                maxCount = Math.max(maxCount, count);
            }
        }
        return maxCount;
    }
}
class Traffic {
    SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss.SSS");
    long startTime;
    long endTime;
    float processingTime;

    Traffic(String line){
        parseLog(line);
    }

    private void parseLog(String line){
        String[] logs = line.split(" ");
        this.processingTime = Float.parseFloat(logs[2].split("s")[0]);
        try {
            this.endTime = dateFormat.parse(logs[0] + " " + logs[1]).getTime();
            this.startTime = endTime - (long)(processingTime*1000) + 1;
        } catch (Exception e){
            System.out.println("데이터 포맷 에러");
            e.printStackTrace();
        }
    }
}

 

반응형