-
[CodeKata] 프로그래머스 : 8.15(일), 광고 삽입Algorithm 2021. 8. 15. 16:45반응형
🥋 Oooth More!! (Level 3)
🧮 풀이
* 실패한 풀이이다. 극소 케이스는 맞았으나, 대부분 실패나 시간초과가 발생했음.
function toSec(time) { time = time.split(":"); return Number(time[0] * 3600 + time[1] * 60 + time[2]); } function solution(play_time, adv_time, logs) { function getPlays(start, end, logs) { let play = 0; logSecs.forEach((log) => { if (log[1] < start || log[0] > end) return; play += (Math.min(log[1], end) - Math.max(log[0], start)); }) return play; } const playtime = toSec(play_time); const advtime = toSec(adv_time); const logSecs = logs.map((log, i) => [...log.split("-").map(time => toSec(time)), i]).sort((a,b) => a[0]-b[0]) let totalPlays = getPlays(0, advtime); let answer = -1; logSecs.forEach(([s,e,i]) => { const nowPlays = getPlays(s, Math.min(playtime, s+advtime)); if (nowPlays > totalPlays) { totalPlays = nowPlays answer = i } }) return answer === -1 ? "00:00:00" : logs[answer].substr(0,8); }
0초와, 각 재생기록들의 시작시간마다 공익광고가 시작된다고 가정한 뒤, 각 경우의 총 재생시간(getPlays)을 비교하여 이를 최신화했다.
'HH:mm:ss' 포멧을 초로 계산(toSec)한 뒤, 시간 차이값들의 합이 가장 큰 값으로 누적하여 이 시작시간을 최종적으로 반환했다.
🖇 리뷰
function solution (play_time, adv_time, logs) { const pt = calculateTime(play_time); const at = calculateTime(adv_time); const times = new Array(pt).fill(0); logs.forEach(log => { const [start, end] = log.split('-'); const ws = calculateTime(start); const we = calculateTime(end); times[ws]++; times[we]--; }); // 시청자수 for(let i = 1; i <= pt; i++) times[i] += times[i-1]; // 시청시간 for(let i = 1; i <= pt; i++) times[i] += times[i-1]; let sum = times[at-1]; let idx = 0; for(let i = at-1; i < pt; i++) { if(sum < times[i] - times[i-at]) { sum = times[i] - times[i-at]; idx = i - at + 1; } } return formatterTime(idx); } const calculateTime = (time) => { const HHMMSS = time.split(':'); const amount = HHMMSS[0]*3600 + HHMMSS[1]*60 + HHMMSS[2]*1; return amount; } const formatterTime = (time) => { let HH = time / 3600 >> 0; let MM = (time / 60 >> 0) % 60; let SS = time % 60; HH = HH > 9 ? HH : '0' + HH; MM = MM > 9 ? MM : '0' + MM; SS = SS > 9 ? SS : '0' + SS; return `${HH}:${MM}:${SS}` }
- calculateTime() 은 시간문구를 초값으로, formatterTime은 초값을 시간문구로 변환해주는 상반되는 메서드들이다.
- play_time, adv_time, logs의 [start, end] 변환에 calculateTime()이 사용된다. times는 pt만큼 1초단위로 만든 배열이다.
- logs를 순회하며, 각 log가 시작되는 시간의 times엔 1을 더하고, 끝나는 times엔 1을 뺀다.
- times를 순회하며, times[i]에 times[i-1]을 더해준다. 이러면 모든 초에서, 시청하고있는 사람수로 계산되는 것이다.
- 이 for문이 한번 더 돈다. 이렇게 되면, 사람수들이 뒤로 계속 누적되므로 해당 시간까지의 누적 재생횟수가 되는 것이다.
- 가장 먼저, 영상을 0초(idx)에서 틀었다고 가정하면, 누적 재생횟수는 at만큼 지난 times[at-1] 값이 해당될 것이다.
- 그런 다음, at-1부터 pt까지 times를 순회한다. times[i] - times[i-at]가 해당 광고재생동안 누적 재생횟수가 된다. 이 값이, 현재 sum보다 큰 경우 최대값을 최신화하고, idx는 시작값인 i - at + 1로 최신화하면 된다.
- 이 idx값이 우리가 찾는 정답이자 시작시간이다. 이를, formatterTime()을 통해 시간문구로 변환하여 반환하면 된다.
LV3이라 어렵기도 하고 예전에 비해 시간투자를 많이 못하고 있긴 하나, 이번 문제도 고도의 알고리즘을 사용하는 문제는 아니었다.
문제를 풀 수 있는 방법과 다양한 시도를 좀 더 적용해본 뒤에, 모범답안을 학습할 수 있도록 알고리즘에 일정시간을 할당해버릇 해야겠다.
반응형'Algorithm' 카테고리의 다른 글
[CodeKata] 프로그래머스: 10.11(월), 길 찾기 게임 (0) 2021.10.11 [CodeKata] 프로그래머스 : 8.22(일), 기둥과 보 설치 (0) 2021.08.22 [CodeKata] 프로그래머스 : 8.8(일), 섬 연결하기 (0) 2021.08.11 [CodeKata] 프로그래머스 : 7.19(월), 여행경로 / 베스트앨범 (0) 2021.07.20 [CodeKata] 프로그래머스 : 7.10(토), 경주로 건설 (0) 2021.07.10