N

(프로그래머스 KAKAO JS)광고 삽입 본문

프로그래머스 알고리즘/KAKAO

(프로그래머스 KAKAO JS)광고 삽입

naeunchan 2022. 2. 16. 11:34
728x90
반응형

https://programmers.co.kr/learn/courses/30/lessons/72414

 

코딩테스트 연습 - 광고 삽입

시간을 나타내는 HH, H1, H2의 범위는 00~99, 분을 나타내는 MM, M1, M2의 범위는 00~59, 초를 나타내는 SS, S1, S2의 범위는 00~59까지 사용됩니다. 잘못된 시각은 입력으로 주어지지 않습니다. (예: 04:60:24, 11

programmers.co.kr

 

누적합 관련 문제.

IMOS 알고리즘을 사용했다.

 

-변수 및 함수 설명-

time: 정답을 구한 시간(number)

sum: 광고 누적 시간의 최대값

imos배열 : 광고 누적합을 구하기 위한 배열

 

calculateSecond 함수: 들어온 시,분,초를 초 단위로 변환해 모두 더해 값을 리턴한다.

 

splitAndConvert 함수: 문자열 형태의 시간을 ":"로 split 한 후, number로 변환해 리턴한다.

(리턴 값은 [h, m, s]가 된다.)

 

playTime과 advTime은 각각 [ph, pm, ps], [ah, am, as]를 초 단위로 변환해 저장한다.

 

timeFormat함수는 시간을 구한 뒤, 정답의 형태인 "HH:MM:SS"로 리턴하는 함수다.

 

-답 구하기-

만약 playTime과 advTime이 같다면 "00:00:00"을 바로 리턴한다.

 

그렇지 않다면 광고 누적 시간을 구한다.

 

1) logs 배열을 순회.

for of문을 이용해 logs를 차례대로 log라는 변수로 접근한다.

log를 우선 "-"로 split 하여 광고 시작 시간과 종료 시간을 각각 [start, end]에 저장한다.

[sh, sm, ss] = start를 splitAndConvert 함수를 이용해 number 형태로 변환

[eh, em, es] = end를 splitAndConvert 함수를 이용해 number 형태로 변환

 

startTime과 endTime을 calculateSecond 함수를 이용해 초 단위로 변환하여,

imos 배열에 각 인덱스로 접근해 +1, -1을 계산한다.

 

2) imos 배열 순회- 첫번째

광고 시간의 누적합을 구한다.

 

3) imos 배열 순회- 두번째

누적된 광고 시간을 시청한 누적합을 구한다.

 

4) 광고 시청 시간의 최대값 구하기.

sum = imos[advTime - 1]로 저장하고 for문을 진행한다.

for문은 advTime - 1 ~ playTime 까지 진행한다.

 

sum은 결국 누적된 광고 시간의 최대 누적합을 뜻하게 되므로,

sum이 갱신되면 해당 인덱스를 time 변수에 마찬가지로 갱신하면 된다.

 

time을 timeFormat 함수로 전달해 format에 맞게 변환하여 리턴하면 된다.

const solution = (play_time, adv_time, logs) => {
    let time = 0;
    let sum = 0;
    
    const calculateSecond = (h, m, s) => (h * 3600) + (m * 60) + s;
    
    const splitAndConvert = (time) => time.split(":").map((v) => parseInt(v));
    
    const [ph, pm, ps] = splitAndConvert(play_time);
    const [ah, am, as] = splitAndConvert(adv_time);
    const playTime = calculateSecond(ph, pm, ps);
    const advTime = calculateSecond(ah, am, as);
    const imos = Array(playTime + 1).fill(0);
    
    const timeFormat = (time) => {
        const h = Math.floor(time / 3600);
        const m = Math.floor(time % 3600 / 60);
        const s = time % 3600 % 60;
        
        return `${h < 10 ? "0" : ""}${h}:${m < 10 ? "0" : ""}${m}:${s < 10 ? "0" : ""}${s}`
    }
    
    if(playTime === advTime){
        return "00:00:00";
    }
    
    for(const log of logs){
        const [start, end] = log.split("-");
        const [sh, sm, ss] = splitAndConvert(start);
        const [eh, em, es] = splitAndConvert(end);
        const startTime = calculateSecond(sh, sm, ss);
        const endTime = calculateSecond(eh, em, es);
        
        imos[startTime]++;
        imos[endTime]--;
    }
    
    for(let i = 1; i <= playTime; i++){
        imos[i] += imos[i - 1];
    }
    
    for(let i = 1; i <= playTime; i++){
        imos[i] += imos[i - 1];
    }
    
    sum = imos[advTime - 1];
    
    for(let i = advTime - 1; i < playTime; i++){
        const aTime = imos[i] - imos[i - advTime];
        
        if(sum < aTime){
            sum = aTime;
            time = i - advTime + 1;
        }
    }
    
    return timeFormat(time);;
}
728x90
반응형