문제
코딩테스트 연습 - 광고 삽입
시간을 나타내는 HH, H1, H2의 범위는 00~99, 분을 나타내는 MM, M1, M2의 범위는 00~59, 초를 나타내는 SS, S1, S2의 범위는 00~59까지 사용됩니다. 잘못된 시각은 입력으로 주어지지 않습니다. (예: 04:60:24, 11
programmers.co.kr
풀이
추석 트래픽 문제와 동일하다고 생각해서 같이 풀었는데 시간 초과가 걸려버렸다
programmers. 추석 트래픽
문제 문제 풀이 우선 들어오는 입력은 "2016-09-15 01:00:04.001 2.0s" 의 날짜, 작업 종료 시각, 작업 시간 형태로 들어온다 모든 입력이 2016-09-15까지 동일하기 때문에 날짜는 신경쓸 필요가 없다고 생각
code-anthropoid.tistory.com
풀이를 찾아보니 투 포인터, 슬라이딩 윈도우를 사용하여 풀어야하는데
나는 존재 조차 몰랐지만 추석 트래픽에서는 배열의 크기가 너무 커서 일반적인 슬라이딩 윈도우 방식으로는 풀 수가 없었다고 한다..
기본적인 풀이는 죠르디의 영상 시간 만큼의 크기를 가진 배열을 모두 0으로 초기화하고 사람이 재생한 구간은 1씩 늘린다
그 배열을 투 포인터 방식으로 순회하며 가장 높았던 구간을 찾는 것
초 변환
역시나 이런 문제는 시간, 분, 초 단위를 모두 초로 환산해서 계산하는 것이 편하다
function transTime(time, option = true){
if(option){
const [h,m,s] =time.split(':');
return h*3600 + m*60 + s*1;
}
const h = Math.floor(time/3600).toString();
const m = Math.floor((time%3600)/60).toString();
const s = Math.floor(((time%3600)%60)%60).toString();
return `${h.length===1 ? '0'+h : h}:${m.length===1 ? '0'+m : m}:${s.length===1 ? '0'+s : s}`
}
true/false의 option 값을 주어서 시간 -> 초, 초 -> 시간 모두 구현하여 하나의 함수에 묶어서
나중에 정답을 리턴할 때도 사용할 수 있도록 했다
배열 초기화
const viewer = Array(playTime+1).fill(0);
logs.forEach((log) => {
const [start, end] = log.split('-').map(v=>transTime(v));
viewer[start]++;
viewer[end]--;
});
for(let i=1;i<=playTime;i++) viewer[i] += viewer[i-1];
재생 크기 만큼 0으로 초기화한 배열에
주어진 재생 구간, log를 초 단위로 바꾼 뒤 시작부분을 1늘리고, 종료시점을 1줄인다
그 뒤 배열 인덱스 1부터 i값 = i값 + i-1의 값 하면 재생 구간의 누적 수를 구할 수 있다
가장 놀라웠던 코드 나는 죽었다 깨어나도 이런 수학적 사고는 스스로 할 수 없을텐데.. 노력해야겠다
투 포인터
while (right<playTime){
time -= viewer[left];
time += viewer[right];
if(time>max){
max = time;
start = left+1;
}
left++;
right++;
}
0부터 광고 시간만큼 미리 값을 구한 뒤 투 포인터로 배열 마지막까지 순회하는 코드다
전체 코드
function solution(play_time, adv_time, logs) {
if(play_time===adv_time) return '00:00:00';
const minAdv = transTime(adv_time);
const playTime = transTime(play_time);
const viewer = Array(playTime+1).fill(0);
logs.forEach((log) => {
const [start, end] = log.split('-').map(v=>transTime(v));
viewer[start]++;
viewer[end]--;
});
for(let i=1;i<=playTime;i++) viewer[i] += viewer[i-1];
let time = 0;
for(let i=0; i<minAdv;i++) time += viewer[i];
let [left,right] = [0,minAdv];
let max = time;
let start= 0;
while (right<playTime){
time -= viewer[left];
time += viewer[right];
if(time>max){
max = time;
start = left+1;
}
left++;
right++;
}
return transTime(start,false);
function transTime(time, option = true){
if(option){
const [h,m,s] =time.split(':');
return h*3600 + m*60 + s*1;
}
const h = Math.floor(time/3600).toString();
const m = Math.floor((time%3600)/60).toString();
const s = Math.floor(((time%3600)%60)%60).toString();
return `${h.length===1 ? '0'+h : h}:${m.length===1 ? '0'+m : m}:${s.length===1 ? '0'+s : s}`
}
}
'Algorithm > 문제' 카테고리의 다른 글
baekjoon. 괄호의 값 (0) | 2021.05.26 |
---|---|
programmers. 기둥과 보 설치 (0) | 2021.05.06 |
programmers. 길 찾기 게임 (0) | 2021.05.04 |
programmers. 합승 택시 요금 (0) | 2021.05.02 |
programmers. 불량 사용자 (0) | 2021.05.01 |