- 누적합을 모른다면 사실상 시간 안에 풀 수 없는 문제
Solution
Python
from typing import List
def to_second(time: str) -> int:
second = 0
time_split = time.split(':')
h, m, s = time_split[0], time_split[1], time_split[2]
if h < '10':
second += int(h[1]) * 60 * 60
else:
second += int(h) * 60 * 60
if m < '10':
second += int(m[1]) * 60
else:
second += int(m) * 60
if s < '10':
second += int(s[1])
else:
second += int(s)
return second
def to_time(second: int) -> str:
h = second // 3600
m = (second % 3600) // 60
s = second % 60
return to_time_str(h) + ':' + to_time_str(m) + ':' + to_time_str(s)
def to_time_str(num: int) -> str:
if num < 10:
return '0' + str(num)
return str(num)
def solution(play_time: str, adv_time: str, logs: List[str]) -> str:
answer = 0
play_time_second = to_second(play_time)
adv_time_second = to_second(adv_time)
# 초당 시청자 수 (누적합 배열)
total_viewer_for_second = [0 for _ in range(play_time_second + 1)]
# 각 구간의 시청자 수 체크
# total_viewer_for_second[time] = (time 시각에 시작한 시청자 수) - (time 시각에 종료한 시청자 수)
for log in logs:
start, end = log.split('-')
start_sec = to_second(start)
end_sec = to_second(end)
total_viewer_for_second[start_sec] += 1
total_viewer_for_second[end_sec] -= 1
# 누적합 계산 1회 (1초 간격으로 누적합 계산)
# total_viewer_for_second[time] = (time 시각부터 time + 1 시각까지의 1초간의 구간을 포함한 시청자 수)
for i in range(1, len(total_viewer_for_second)):
total_viewer_for_second[i] += total_viewer_for_second[i - 1]
# 누적합 계산 2회 (해당 초까지의 누적 시청자 계산)
# total_viewer_for_second[time] = (0초부터 time + 1 시각까지의 구간을 포함한 누적 시청자 수)
for i in range(1, len(total_viewer_for_second)):
total_viewer_for_second[i] += total_viewer_for_second[i - 1]
max_viewer_from_zero_time = total_viewer_for_second[adv_time_second - 1]
for i in range(0, len(total_viewer_for_second) - adv_time_second):
target = total_viewer_for_second[i + adv_time_second] - total_viewer_for_second[i]
if target > max_viewer_from_zero_time:
max_viewer_from_zero_time = target
answer = i + 1
print(answer)
return to_time(answer)
print(solution("02:03:55", "00:14:15",
["01:20:15-01:45:14", "00:40:31-01:00:00", "00:25:50-00:48:29", "01:30:59-01:53:29",
"01:37:44-02:02:30"]))
Java
package programmers.sully.week39;
public class InsertAd {
public static long toSecond(String time) {
long second = 0;
String[] timeSplit = time.split(":");
int h = Integer.parseInt(timeSplit[0]);
int m = Integer.parseInt(timeSplit[1]);
int s = Integer.parseInt(timeSplit[2]);
second += h < 10 ? Integer.parseInt(timeSplit[0].substring(1)) * 60 * 60 : h * 60 * 60;
second += m < 10 ? Integer.parseInt(timeSplit[1].substring(1)) * 60 : m * 60;
second += s < 10 ? Integer.parseInt(timeSplit[2].substring(1)) : s;
return second;
}
public static String toTime(long second) {
long h = second / 3600;
long m = (second % 3600) / 60;
long s = second % 60;
return toTimeStr(h) + ":" + toTimeStr(m) + ":" + toTimeStr(s);
}
public static String toTimeStr(long num) {
return num < 10 ? "0" + num : String.valueOf(num);
}
public static String solution(String playTime, String advTime, String[] logs) {
long answer = 0;
long playTimeSecond = toSecond(playTime);
long advTimeSecond = toSecond(advTime);
// 초당 시청자 수 (누적합 배열)
long[] totalViewerForSecond = new long[(int) (playTimeSecond + 1)];
// 각 구간의 시청자 수 체크
// totalViewerForSecond[time] = (time 시각에 시작한 시청자 수) - (time 시각에 종료한 시청자 수)
for (String log : logs) {
String[] logSplit = log.split("-");
long startSec = toSecond(logSplit[0]);
long endSec = toSecond(logSplit[1]);
totalViewerForSecond[(int) startSec]++;
totalViewerForSecond[(int) endSec]--;
}
// 누적합 계산 1회 (1초 간격으로 누적합 계산)
// totalViewerForSecond[time] = (time 시각부터 time + 1 시각까지의 1초간의 구간을 포함한 시청자 수)
for (int i = 1; i < totalViewerForSecond.length; i++) {
totalViewerForSecond[i] += totalViewerForSecond[i - 1];
}
// 누적합 계산 2회 (해당 초까지의 누적 시청자 계산)
// totalViewerForSecond[time] = (0초부터 time + 1 시각까지의 구간을 포함한 누적 시청자 수)
for (int i = 1; i < totalViewerForSecond.length; i++) {
totalViewerForSecond[i] += totalViewerForSecond[i - 1];
}
long maxViewerFromZeroTime = totalViewerForSecond[(int) (advTimeSecond - 1)];
for (int i = 0; i < totalViewerForSecond.length - advTimeSecond; i++) {
long target = totalViewerForSecond[i + (int) advTimeSecond] - totalViewerForSecond[i];
if (target > maxViewerFromZeroTime) {
maxViewerFromZeroTime = target;
answer = i + 1;
}
}
System.out.println(answer);
return toTime(answer);
}
}
Reference
Leave a comment