[2021 KAKAO BLIND RECRUITMENT] 광고 삽입

최민길(Gale)·2023년 4월 14일
1

알고리즘

목록 보기
69/172

문제 링크 : https://school.programmers.co.kr/learn/courses/30/lessons/72414#fn1

이 문제는 문제의 조건을 어떤 식으로 구현할 것인지를 떠올리면 풀 수 있습니다. 우선 시간:분:초의 형태를 계산하기 편하게 초 단위로 변환합니다. 이후 logs의 시작 시간과 종료 시간을 체크해서 전체 런타임 중 x 시각에 시작된 재생 구간이 존재할 경우 1씩 증가하고 종료된 재생 구간이 존재할 경우 1씩 감소하는 배열을 설정합니다. 그럼 이 배열에는 전체 런타임 중 재생 및 종료의 정보가 기입됩니다.

위에서 만든 배열에서 직전 인덱스의 값과의 합한 배열을 새로 정의합니다. (dp[i] = dp[i]+dp[i-1]) 이 배열은 i 시간부터 i+1까지 시작 및 종료의 정보가 기입됩니다. 여기서 더 확장해서 방금 구한 배열의 직전 인덱서의 값과의 합한 배열을 새로 정의하게 된다면 이 배열은 0부터 1까지, 1부터 2까지 , ... , i부터 i+1까지 구간의 시작 및 종료 정보가 기입됩니다. 즉 0부터 i+1 구간의 누적 재생 시간을 얻게 됩니다.

위에서 구한 누적 재생 시간 배열에서 광고 시간만큼 인덱스의 차를 주어 더해준다면 (dp[i] - dp[i-at]) 광고 시간 동안의 누적 재생 시간을 구할 수 있습니다. 이 값이 최대가 되는 시작 시간을 리턴하여 시간값으로 변환시키면 됩니다. 글에서 작성한 방식은 광고가 끝나는 시간을 기준으로 반복문을 돌렸습니다. 만약 광고의 시작 시간을 기준으로 돌리고 싶으시다면 dp[i+at] - dp[i]로 설정하셔도 됩니다.

다음은 코드입니다.

import java.util.*;

class Solution {
    static int convert(String time){
        String[] arr = time.split(":");
        int hour = Integer.parseInt(arr[0])*60*60;
        int minute = Integer.parseInt(arr[1])*60;
        int second = Integer.parseInt(arr[2]);
        
        return hour + minute + second;
    }
    
    public String solution(String play_time, String adv_time, String[] logs) {
        int pt = convert(play_time);
        int at = convert(adv_time);
        
        // total_time[x] = x 시각에 시작된 재생 구간의 개수 – x 시각에 종료된 재생구간의 개수
        long[] total_time = new long[pt+1];
        for(int i=0;i<logs.length;i++){
            String[] arr = logs[i].split("-");
            total_time[convert(arr[0])]++;
            total_time[convert(arr[1])]--;
        }
        
        // total_time[x] = 시각 x부터 x+1까지 1초 간의 구간을 포함하는 재생 구간의 개수
        for(int i=1;i<=pt;i++) total_time[i] += total_time[i-1];
        
        // total_time[x] = 시각 0부터 x+1까지 x+1초 간의 구간을 포함하는 누적 재생시간
        for(int i=1;i<=pt;i++) total_time[i] += total_time[i-1];
        
        // 0에서 광고가 시작할 경우 total_time[at-1]
        long res = total_time[at-1];
        int idx = 0;
        
        // 광고가 끝나는 시간을 반복문으로 돌려서 최대 누적 재생시간 계산
        for(int i=at;i<=pt;i++){
            // i만큼의 누적 재생시간에서 광고가 시작하기 전인 i-at의 누적 재생시간을 빼면 현재 누적 재생시간 구할 수 있음
            long curr = total_time[i] - total_time[i-at];
            
            // 더 긴 누적 재생 시간이 있을 경우 idx 최신화
            if(res < curr){
                res = curr;
                idx = i-at+1;
            }
        }
        
        // 시간 형식으로 변환
        StringBuilder sb = new StringBuilder();
        int h = idx/3600;
        int m = (idx%3600)/60;
        int s = (idx%3600)%60;
        
        if(h<10) sb.append("0"+h);
        else sb.append(h);
        sb.append(":");
        if(m<10) sb.append("0"+m);
        else sb.append(m);
        sb.append(":");
        if(s<10) sb.append("0"+s);
        else sb.append(s);
        
        return sb.toString();
    }
}

profile
저는 상황에 맞는 최적의 솔루션을 깊고 정확한 개념의 이해를 통한 다양한 방식으로 해결해오면서 지난 3년 동안 신규 서비스를 20만 회원 서비스로 성장시킨 Software Developer 최민길입니다.

0개의 댓글

관련 채용 정보