참고
문제해설
문제 로직고민
NOTE
•
사람들이 영상을 본 시작 시간대에 광고를 배치했을때 최대값이면 결과가 나오지 않을까?
◦
예제 테스트케이스는 모두 통과했던 생각이었다.
◦
광고 시작시간에 놔둔다는것은, 겹치는 경우가 많다는 의미이고 그만큼 많이 본다고 생각했다.
◦
만약 전체 플레이타임을 벗어난다면 그만큼 조정해주는 로직을 추가했다.
◦
하지만 다시 생각해보니 될리가 없었다…
•
질문하기 참고하고 다시 풀이진행, 전체시간 100시간은 36만의 값으로 브루트포스로 가능!
◦
36만크기의 배열에, 구간합을 모두 구한다.
◦
이후 1초마다 옮기면서 광고시간 범위내에서 최대 시청시간값을 구한다.
작성코드
NOTE
import java.util.*;
class Solution {
public String solution(String play_time, String adv_time, String[] logs) {
int pt = convertInt(play_time);
int at = convertInt(adv_time);
int log_cnt = logs.length;
ArrayList<int[]> logList = new ArrayList<int[]>();
// 1. 시간값을 모두 숫자값으로 변환
for(int i=0; i<log_cnt; i++){
String[] s = logs[i].split("-");
int st = convertInt(s[0]);
int et = convertInt(s[1]);
int[] log = {st, et};
logList.add(log);
}
// 2. 시간이 빠른순으로 정렬
Collections.sort(logList, (a1,a2) -> a1[0] - a2[0]);
// 3. 각 시청시간의 시작지점을 기준으로 광고배치를 했을때 가장 많이 보는경우를 구한다.
int idx = 0;
int cnt = 0;
for(int i=0; i<log_cnt; i++){
int st = logList.get(i)[0];
int et = st + at;
int temp = 0;
for(int j=i; j<log_cnt; j++){
int[] log = logList.get(j);
if(et < log[0]) break; // 광고 범위를 벗어난다.
else if(et < log[1]) temp += et - log[0]; // 포함은 되어있으나 시청도중에 광고가 끊긴다.
else temp += log[1] - log[0]; // 광고 범위안에 모든 시청시간이 포함된다.
}
if(cnt < temp) {
cnt = temp;
idx = i;
}
}
String answer;
if(logList.get(idx)[0] + at > pt){
answer = convertString(logList.get(idx)[0] - (logList.get(idx)[0] + at - pt));
}
else{
answer = convertString(logList.get(idx)[0]);
}
return answer;
}
private int convertInt(String time){
String[] s = time.split(":");
return Integer.parseInt(s[0]) * 3600 + Integer.parseInt(s[1]) * 60 + Integer.parseInt(s[2]);
}
private String convertString(int time){
int h = time / 3600;
int m = (time % 3600) / 60;
int s = time % 60;
return String.format("%02d:%02d:%02d", h, m, s);
}
}
Java
복사
16.1 / 100.0
•
당연히 야매로 풀어서 안될줄알았는데 기본 테스트케이스가 통과해서 설랬다..
•
결과는 처참하다.
import java.util.*;
class Solution {
public String solution(String play_time, String adv_time, String[] logs) {
int pt = convertInt(play_time);
int at = convertInt(adv_time);
int log_cnt = logs.length;
int[] time = new int[pt+1];
// 1. 시간값을 모두 숫자값으로 변환 (로그는 최대 30만개)
for(int i=0; i<log_cnt; i++){
String[] s = logs[i].split("-");
int st = convertInt(s[0]);
int et = convertInt(s[1]);
time[st]++;
time[et]--;
}
// 2. 전체 시간을 누적합으로 계산해둔다. (최대 36만개)
for(int i=1; i<time.length; i++){
time[i] += time[i-1];
}
// 3.가장 구간합이 큰 구간을 구한다. (최대 36만개)
int answer = 0;
long interval_time = 0; // long으로 선언해야 17번 태케통과함
for(int i=0; i<at; i++){ // 최초 구간합
interval_time += time[i];
}
long max = interval_time; // 9, 31번이 틀렸던 이유.. (초기 max를 0으로 냅둠)
for(int i=0, j=at; j<pt; i++, j++){ // 1초씩 움직이며 투포인터 계산
interval_time += time[j];
interval_time -= time[i];
if(interval_time > max){
answer = i+1;
max = interval_time;
}
}
return convertString(answer);
}
private int convertInt(String time){
String[] s = time.split(":");
return Integer.parseInt(s[0]) * 3600 + Integer.parseInt(s[1]) * 60 + Integer.parseInt(s[2]);
}
private String convertString(int time){
int h = time / 3600;
int m = (time % 3600) / 60;
int s = time % 60;
return String.format("%02d:%02d:%02d", h, m, s);
}
}
Java
복사
정답코드!
•
약간의 힌트를 얻고나서 풀이를 다시 진행했다. 전체적인 흐름은 알았는데 중간중간 실수를 잡는데 오래 걸렸다.
◦
17번 테스트케이스 : logs(최대 30만) * 시간최대범위(36만) == Integer 범위초과..
◦
9, 31번 테스트케이스 : 초기 max값을 누적합으로 수정하지 않고 0으로 놔두는 경우.
다른사람 풀이
NOTE
import java.util.Arrays;
class Solution {
public String solution(String play_time, String adv_time, String[] logs) {
int playTime = parseTime(play_time);
int advTime = parseTime(adv_time);
long playNums[] = new long[playTime+10];
for(String log : logs){
String splitted[] = log.split("-");
playNums[parseTime(splitted[0])]++;
playNums[parseTime(splitted[1])]--;
}
for(int i = 0; i < playNums.length-1; i++)
playNums[i+1] += playNums[i];
int startTime = 0;
long timeSum = 0;
long max = timeSum;
long maxStartTime = 0;
while(startTime+advTime <= playTime){
if(max < timeSum){
max = timeSum;
maxStartTime = startTime;
}
timeSum -= playNums[startTime];
timeSum += playNums[startTime+advTime];
startTime++;
}
return String.format("%02d:%02d:%02d",
maxStartTime/3600,
(maxStartTime/60)%60,
maxStartTime%60);
}
int parseTime(String time){
String splitted[] = time.split(":");
return Integer.parseInt(splitted[0])*3600
+ Integer.parseInt(splitted[1])*60
+ Integer.parseInt(splitted[2]);
}
}
Java
복사
깔끔한 풀이법.. (로직은 동일)