광고 삽입
https://programmers.co.kr/learn/courses/30/lessons/72414
풀이
function solution(play_time, adv_time, logs) {
// 시간 변경 함수
const addZero = (time) => parseInt(time).toString().padStart(2, "0");
const convertToHHMMSS = (time) =>
addZero(time / 3600) + ":" +
addZero((time % 3600) / 60) + ":" +
addZero((time % 3600) % 60);
const convertToSeconds = ([hour, min, sec]) => hour * 3600 + min * 60 + +sec;
const changeTime = (time) => convertToSeconds(time.split(":"));
// HH:MM:SS 형식을 초단위로 변경
const playTime = changeTime(play_time);
const advTime = changeTime(adv_time);
const userLogs = logs.map((log) => log.split("-").map(changeTime));
// 시간별로 조회수를 기록한 배열 생성 후 0으로 초기화
let views = Array(playTime).fill(0);
// logs를 돌며 들어가고 나가는 부분에 표시
userLogs.forEach(([start, end]) => {
views[start] += 1;
views[end] -= 1;
});
// 누적 조회수를 만들기 위한 반복문
const getCumulativeView = (arr) => {
for (let i = 1, len = arr.length; i < len; i++) {
arr[i] += arr[i - 1];
}
};
getCumulativeView(views); // 시작, 끝부분에만 표시를 했기 때문에, 중간의 빈 시간을 채워줌
getCumulativeView(views); // 한번 더 반복하면서 조회수가 누적됨
// 각 시간 별 누적 조회수를 비교
const result = views.reduce(
(max, view, index) => {
const totalView = views[index + advTime] - view;
return totalView > max[0] ? [totalView, index + 1] : max;
},
[views[advTime - 1] - views[0], 0]
)[1];
return convertToHHMMSS(result);
}
동영상의 길이는 00:00:01
이상 99:59:59
이하이다. 가장 긴 시간인 99:59:59
를 초단위로 환산하면 359999
이므로 광고 길이의 배열을 생성해도 문제 없다.
먼저, 주어진 시간들을 초단위로 변경해주었다.
// HH:MM:SS 형식을 초단위로 변경
const playTime = changeTime(play_time);
const advTime = changeTime(adv_time);
const userLogs = logs.map((log) => log.split("-").map(changeTime));
// 시간별로 조회수를 기록한 배열 생성 후 0으로 초기화
let views = Array(playTime).fill(0);
동영상의 길이 만큼의 배열을 생성해주고 0으로 초기화 해준다. 여기에 누적 조회수가 담길 것이다.
초단위로 누적 조회수를 구해놓는다면 보다 쉽게 어떤 구간이 누적 조회수를 제일 많이 기록하는지 알기 쉽다.
만약 views = [ 0, 0, 1, 2, 2, 3, 4, 6, 8, 8]
이라면 4에서 7까지의 누적 조회수를 구할 때 views[7] - views[4]
만 해주면 값을 쉽게 구할 수 있다.
// logs를 돌며 들어가고 나가는 부분에 표시
userLogs.forEach(([start, end]) => {
views[start] += 1;
views[end] -= 1;
});
우선은 logs
를 돌면서 들어가는 부분에 +1
나가는 부분에 -1
을 더해 기록을 표시해준다.
// 누적 조회수를 만들기 위한 반복문
const getCumulativeView = (arr) => {
for (let i = 1, len = arr.length; i < len; i++) {
arr[i] += arr[i - 1];
}
};
getCumulativeView(views); // 시작, 끝부분에만 표시를 했기 때문에, 중간의 빈 시간을 채워줌
getCumulativeView(views); // 한번 더 반복하면서 조회수가 누적됨
그리고 표시한 배열을 돌면서 이전 시간의 값을 더해준다.
한 번 반복하면 시작, 끝 부분에만 표시했던 조회수 기록을 채워주게 된다.
만약 10초의 동영상 길이에 logs
가 2초 ~ 4초, 7초 ~ 9초, 5초 ~ 9초라면, 처음 시작, 끝부분만 표시한 배열은 [ 0, 0, 1, 0, -1, 1, 0, 1, 0, -2]
이 된다.
이 배열을 한번 순회하면서 이전 값을 더해준다면 [ 0, 0, 1, 1, 0, 1, 1, 2, 2, 0]
이되면서 중간에 비어있던 값들이 채워진다.
우리가 원하는건 시간 마다의 누적 시청자 수이기 때문에 한번 더 반복한다.
시간 별 시청자 수가 담긴 배열을 한번 더 순회하며 이전 값을 더해주면[ 0, 0, 1, 2, 2, 3, 4, 6, 8, 8
이 된다. 이제 각 시간 까지의 누적된 시청자 수가 배열에 담기게 된다.
이제 다시 views
를 돌면서 각 지점을 시작점으로 advTime
까지의 누적 시청자 수를 구한다.
// 각 시간 별 누적 조회수를 비교
const result = views.reduce(
(max, view, index) => {
const totalView = views[index + advTime] - view;
return totalView > max[0] ? [totalView, index + 1] : max;
},
[views[advTime - 1] - views[0], 0]
)[1];
누적 시청자수 비교를 위해 누적 시청자 수
와 결과적으로는 누적 시청자 수가 가장 많은 구간의 시작 지점을 반환해야하기 때문에 시작 시간
을 기록해 놔야 한다. 따라서 .reduce
의 리턴 값은 [누적 시청자수, 시작 시간 ( 배열의 인덱스 )]
로 해준다.
return convertToHHMMSS(result);
누적 시청자 수가 가장 많은 구간을 구했다면 시작 시간만을 가져와 다시 HH:MM:SS
형태로 변경 후 return해준다.