[프로그래머스] 레벨3 (level3) 광고 삽입
2021년 03월 11일, 08:00
광고 삽입
문제 풀이
누적합을 이용해서 푸는 문제이다. 문제에서 주어진 playtime은 100시간을 넘지 않으므로 100시간을 초로 바꾸면 360000초 배열로 둘 수 있다. 배열로 두고 배열의 각 인덱스는 1초를 가리키므로 해당 구간의 재생시간을 구하면 된다.
- 주어진 logs 배열로 totalTime을 초기화 시킨다.
- 시청자들의 시청 시간을 초로 바꾼다.
- 시작시간에는 +1을 해준다.
- 끝나는 시간엔 -1을 해준다.
- totalTime[i] += totalTime[i-1]을 playtime까지 for문을 돌려준다.
- logs배열로 시청자들의 재생 시작 시간, 재생 끝나는 시간을 표시했으므로 totalTime[i] += totalTime[i-1]을 돌리면 해당 구간에서 재생한 시청자 수가 나온다.
totalTime이 아래와 같이 된 경우 for문을 돌리게 되면, index 0 1 2 3 4 5 6 7 8 9 10 value 0 0 1 0 1 0 -1 0 0 0 -1 index 0 1 2 3 4 5 6 7 8 9 10 value 0 0 1 1 2 2 1 1 1 1 0 위와 같이 해당 초 구간을 재생한 시청자들을 알게 된다.
- logs배열로 시청자들의 재생 시작 시간, 재생 끝나는 시간을 표시했으므로 totalTime[i] += totalTime[i-1]을 돌리면 해당 구간에서 재생한 시청자 수가 나온다.
- 한번 더 totalTime[i] += totalTime[i-1]을 playtime까지 for문을 돌려준다.(누적합)
- 광고 구간에 대한 누적 재생시간을 알기 위해서 for문을 한번 더 돌린다.
- 구한 누적합을 바탕으로, 0
playtime-adtime까지 for문을 돌리면서, iadTime+i을 광고 구간으로 두고 누적합이 가장 큰 경우를 찾으면 된다.
구한 시작 지점에 +1를 하는 이유?
시청자들의 재생 시작 시간, 재생 끝나는 시간을 표시한 배열(logs를 for문) index 0 1 2 3 4 5 6 7 8 9 10 value 0 0 1 0 1 0 -1 0 0 0 -1 각 구간의 시청자들의 재생 횟수를 표시한 배열(totalTime[i] += totalTime[i-1]를 for문) index 0 1 2 3 4 5 6 7 8 9 10 value 0 0 1 1 2 2 1 1 1 1 0 구간까지의 누적합 배열(totalTime[i] += totalTime[i-1]를 for문) index 0 1 2 3 4 5 6 7 8 9 10 11 value 0 0 1 2 4 6 7 8 9 10 10 10 겹쳐진 재생시간보다 광고 시간이 작을때는(여기서는 4초라고 하자) totalTime[adTime+i] - totalTime[i]의 값을 구하는 것이니까 1~5인 경우도 6으로 최댓값이라고 볼 수 있다. 하지만 재생 시간의 시작은 2초이므로 +1를 해줘야한다. 그래서 생각해본 경우들은 1씩 차이가 나는 부분이 연속된다고 하면 시청자가 재생하기 전의 시간인 0을 시작지점으로 잡아서 +1을 해줘야하는 것 같다.
소스 코드
const getTime = (time) => {
const [hour, minute, second] = time.split(":");
return Number(hour)*3600 + Number(minute)*60 + Number(second);
}
const padZero2 = (time) => String(time).padStart(2, 0);
const convert = (time) => {
const hour = parseInt(time / 3600);
const minute = parseInt((time % 3600) / 60);
const second = time - hour*3600 - minute*60;
return `${padZero2(hour)}:${padZero2(minute)}:${padZero2(second)}`;
}
function solution(play_time, adv_time, logs) {
const totalTime = Array(360000).fill(0);
const adTime = getTime(adv_time);
const playTime = getTime(play_time);
for(let i=0 ; i<logs.length ; i++){
const [start, end] = logs[i].split("-").map(e => getTime(e));
totalTime[start] += 1;
totalTime[end] -= 1;
}
for(let i=1 ; i<playTime ; i++){
totalTime[i] += totalTime[i-1];
}
for(let i=1 ; i<playTime ; i++){
totalTime[i] += totalTime[i-1];
}
let max = totalTime[adTime];
let start = 0;
for(let i=0 ; i<playTime-adTime ; i++){
if(totalTime[adTime+i] - totalTime[i] > max){
max = totalTime[adTime+i] - totalTime[i];
start = i;
}
}
return start !== 0 ? convert(start+1) : convert(start);
}