알고리즘/PROGRAMMERS (Python)

[ 프로그래머스 / LV3 / 파이썬 Python ] 광고 삽입

Heeto 2023. 4. 23. 17:54
링크 : https://school.programmers.co.kr/learn/courses/30/lessons/72414
 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

코드


# 초를 시간으로 변경
def numToTime(sec):
    h = sec // (60 * 60)
    sec %= (60 * 60)
    m = sec // 60
    sec %= 60
    s = sec
    return '%02d:%02d:%02d' % (h, m, s)
   
# 시간을 초로 변경
def timeToNum(time):
    h,m,s = map(int,time.split(':'))
    return h*3600 + m*60 + s

def solution(play_time, adv_time, logs):
    answer = numToTime(0)
    play_time, adv_time = timeToNum(play_time), timeToNum(adv_time)
    
    # 누적합으로 초마다 인원수 계산
    res = [0] * (play_time+1)
    for log in logs:
        start,end = map(timeToNum,log.split("-"))
        res[start] += 1
        res[end] -= 1      
    for i in range(1,play_time+1):
        res[i] += res[i-1]
    
    # 투포인터를 이용해 최대값 및 정답 갱신
    left = 0
    MAX = total = sum(res[:adv_time])
    for t in range(adv_time,play_time+1):
        total -= res[left]
        total += res[t]
        left += 1
        if total > MAX:
            answer = numToTime(left)
            MAX = total
            
    return answer

 

풀이


요즘 이런 시간에 관련된 문제들을 많이 풀어보고 있는 것 같다. 이번 문제에서는 시간, 분, 초가 주어졌기 때문에 가장 작은 단위인 초를 기준으로 변환하였다. 근데 정말 어렵다...

 

문제의 해결 아이디어는 다음과 같다.

  • 99시간59분59초라는 최대값을 초로 변환하여도 360000정도밖에 되지 않기 때문에 초를 인덱스로 삼는 배열을 생성한다.
  • 재생시간이 해당 시간에 시청중인 시청자의 수에 비례하므로 초마다 시청중인 시청자의 수를 저장한다.
    • 누적합을 이용한다.
    • 시작 시간 += 1, 끝나는 시간 += -1을 해주면 누적합을 진행한 후에 해당 초에 시청중인 시청자의 수가 저장되어 있다.
  • 누적합이 시행된 배열을 광고재생시간 단위로 탐색하며 최대값을 갱신한다.
    • 시간복잡도를 줄이기 위해 슬라이딩 윈도우 + 투포인터를 사용하였다.
    • 초기값을 00:00:00 ~ 광고재생시간으로 잡고 그 이후부터는 1초씩 더해가며 누적재생시간을 갱신하였다.